-
Notifications
You must be signed in to change notification settings - Fork 357
golabels: adjust offset extraction #890
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Adapt the extraction for relative offsets from RIP. Signed-off-by: Florian Lehner <[email protected]>
Co-authored-by: Christos Kalkanis <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a unit test for the new sequence?
Signed-off-by: Florian Lehner <[email protected]>
Signed-off-by: Florian Lehner <[email protected]>
So far we don't know the reason that causes this relative offset from RIP. I can name a bunch of Go executables (each multiple MB in size) that have this relative offset. But adding them to the repo as test feels wrong. |
Signed-off-by: Florian Lehner <[email protected]>
Signed-off-by: Florian Lehner <[email protected]>
Signed-off-by: Florian Lehner <[email protected]>
|
@fabled I did add a unit test with abc27cc as described in #890 (comment). |
Signed-off-by: Florian Lehner <[email protected]>
| ) | ||
|
|
||
| // readMemory is a helper that can be mocked for testing. | ||
| type readMemory func(addr int64, sz, maxSize int) ([]byte, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is not needed. io.ReadAt interface could be used instead. This would allow passing the pfelf.File in the main code path directly (it's ReadAt works on virtual memory). And then just ship a mock object on testing side implementing the inteface. That would avoid generating closures.
| if err != nil { | ||
| break | ||
| } | ||
| pc += op.Len |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The it asm.amd.Interpreter object tracks already pc. Could you instead add PC accessor to it to read it, and use it? I think adding it there would be useful in future.
| // RIP-relative load: mov disp(%rip), %reg | ||
| if mem, ok := op.Args[1].(x86asm.Mem); ok && mem.Base == x86asm.RIP { | ||
| curAddr := int64(sym.Address) + int64(pc) | ||
| if dst, ok := op.Args[0].(x86asm.Reg); ok { | ||
| target := curAddr + int64(mem.Disp) | ||
|
|
||
| // Read 8-byte TLS value from target address | ||
| b, err := extract(target, 8, 8) | ||
| if err == nil && len(b) >= 8 { | ||
| ripRelLoads[dst] = int64(npsr.Uint64(b, 0)) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel that this tracking should be done in the amd.Interpreter, there should a be a new expression type for RIP relative value. That would generalize the code greatly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this feels too complicated at this time, I can do it as a follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for the delay 🙏 I created the follow up with #984.
| // Read 8-byte TLS value from target address | ||
| b, err := extract(target, 8, 8) | ||
| if err == nil && len(b) >= 8 { | ||
| ripRelLoads[dst] = int64(npsr.Uint64(b, 0)) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the rip relative address should be stored to the map, not the dereferenced value. This might do unneeded extra reads. Only the actual rip relative value that is needed, should trigger the dereference. And again, the rip relative PC ideally comes from Interpreter.
| if err != nil { | ||
| t.Fatal(err) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use testify
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| require.NoError(t, err) |
| if offset != 0 { | ||
| t.Fatalf("Expected offset '0' got '%d'", offset) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use testify
| if offset != 0 { | |
| t.Fatalf("Expected offset '0' got '%d'", offset) | |
| } | |
| require.Equal(t, 0, offset) |
Adapt the extraction for relative offsets from RIP.
This is the case that will be supported with this PR: