Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (go version)?
go version go1.9beta2 linux/amd64
What did you do?
Compile this function with -gcflags '-N -l' (context http://github.com/aarzilli/diexplorer)
func openPE(path string) (*dwarf.Data, uint64, []byte) {
file, _ := pe.Open(path)
if file == nil {
return nil, 0, nil
}
fmt.Fprintf(os.Stderr, "Found PE executable\n")
dwarf, err := file.DWARF()
must(err)
var imageBase uint64
switch oh := file.OptionalHeader.(type) {
case *pe.OptionalHeader32:
imageBase = uint64(oh.ImageBase)
case *pe.OptionalHeader64:
imageBase = oh.ImageBase
default:
panic(fmt.Errorf("pe file format not recognized"))
}
sect := file.Section(".text")
if sect == nil {
panic(fmt.Errorf("text section not found"))
}
textStart := imageBase + uint64(sect.VirtualAddress)
textData, err := sect.Data()
must(err)
return dwarf, textStart, textData
}
disassembles to https://play.golang.org/p/Wn2J8N43ws. The problem is the LEA at 0x715c55 it gets assigned to main.go:64 (the return line) when it should be assigned to main.go:59 (the panic line after if sect == nil) you can see that the program jumps there from line 58 and all instructions after it are for line 59. I believe the problem is that the LEA doesn't have a position associated and it gets an automatic one assigned but since it's the first instruction emitted for its block the position is wrong.
The function main.disassemble (from the same repository, I'm not copying it here because it's too long) seems to have the opposite problem (disassembly of that function here: https://play.golang.org/p/XELhHHYCkW) the LEA at 0x714334 gets assigned to disass.go:230 but it should be assigned to disass.go:161 like all the instructions surrounding it.
This two problems aren't common enough that I can find a minimal example to reproduce them but they are common enough that I encounter them in the wild while using delve.
I made a program (http://github.com/aarzilli/badnext) to find such problems with pcln automatically, it works by comparing the CFG derived from parsing the source code with the CFG derived from the disassembly and reporting discrepancies. Usage badnext [-v] check <regex> <executable> checks all functions matching in (doesn't work on anonymous functions).
Sometimes the discrepancies it finds are justifiable but it does find legitimate problems.
The final problem I encounter with the pcln table is that with any code that looks like this:
the if's body is compiled into something that ends with a JMP, and that JMP is assigned the same position as the if's header, it would be better if the JMP had the same position as the last instruction of the body or the same position as the closing brace. This isn't as big a problem as the problem with LEAs above because it's regular enough that you get used to it quickly, but it would be nice if it was fixed.
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version)?What did you do?
Compile this function with
-gcflags '-N -l'(context http://github.com/aarzilli/diexplorer)disassembles to https://play.golang.org/p/Wn2J8N43ws. The problem is the LEA at 0x715c55 it gets assigned to main.go:64 (the return line) when it should be assigned to main.go:59 (the panic line after
if sect == nil) you can see that the program jumps there from line 58 and all instructions after it are for line 59. I believe the problem is that the LEA doesn't have a position associated and it gets an automatic one assigned but since it's the first instruction emitted for its block the position is wrong.The function main.disassemble (from the same repository, I'm not copying it here because it's too long) seems to have the opposite problem (disassembly of that function here: https://play.golang.org/p/XELhHHYCkW) the LEA at 0x714334 gets assigned to disass.go:230 but it should be assigned to disass.go:161 like all the instructions surrounding it.
This two problems aren't common enough that I can find a minimal example to reproduce them but they are common enough that I encounter them in the wild while using delve.
I made a program (http://github.com/aarzilli/badnext) to find such problems with pcln automatically, it works by comparing the CFG derived from parsing the source code with the CFG derived from the disassembly and reporting discrepancies. Usage
badnext [-v] check <regex> <executable>checks all functions matching in (doesn't work on anonymous functions).Sometimes the discrepancies it finds are justifiable but it does find legitimate problems.
The final problem I encounter with the pcln table is that with any code that looks like this:
the if's body is compiled into something that ends with a JMP, and that JMP is assigned the same position as the if's header, it would be better if the JMP had the same position as the last instruction of the body or the same position as the closing brace. This isn't as big a problem as the problem with LEAs above because it's regular enough that you get used to it quickly, but it would be nice if it was fixed.