Skip to content
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

Fix line_table::find_address when the address is the last entry #25

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

boyou
Copy link

@boyou boyou commented Feb 3, 2018

If this extra check is missing, in case the last valid entry in the line table matches the given address, end will still be returned.

Copy link
Owner

@aclements aclements left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the DWARF spec, "Every line number program sequence must end with a
DW_LNE_end_sequence instruction which creates a row whose address is that of the byte
after the last target machine instruction of the sequence." That suggests that, in standards-conforming DWARF, this new code should never trigger because the last entry will always have end_sequence set. Do you have a binary that doesn't satisfy this? What was it built with?

Of course, it's good to follow Postel's law. :) I'm fine with this change as long as we're sure that's what's going on and the new code is commented with something like "Standards-conforming DWARF should always end with an end_sequence, but some tools omit this. Pretend there's an end_sequence one byte past the last entry."

@boyou
Copy link
Author

boyou commented Feb 25, 2018

@aclements , I'm not sure this is about non standard conforming binaries.

For the sample program

void f() {
  int i = 0;
  i += 1;
  i += 2;
}

int main() {
  while (1) {
    f();
  }
  return 0;
}

if I compile with gcc main.c -g -Wall -o main -gdwarf-4 -O0, the assembly code will look like

00000000004004ec <main>:
  4004ec:       55                      push   rbp
  4004ed:       48 89 e5                mov    rbp,rsp
  4004f0:       b8 00 00 00 00          mov    eax,0x0
  4004f5:       e8 dc ff ff ff          call   4004d6 <f>
  4004fa:       eb f4                   jmp    4004f0 <main+0x4>
  4004fc:       0f 1f 40 00             nop    DWORD PTR [rax+0x0]

`
and the line number is

.debug_line: line number info for a single cu
Source lines (from CU-DIE at .debug_info offset 0x0000000b):

<pc>        [row,col] NS BB ET PE EB IS= DI= uri: "filepath"
NS new statement, BB new basic block, ET end of text sequence
PE prologue end, EB epilogue begin
IA=val ISA number, DI=val discriminator value
0x004004d6  [   1, 0] NS uri: "/tmp/pull-request-test/main.c"
0x004004da  [   2, 0] NS
0x004004e1  [   3, 0] NS
0x004004e5  [   4, 0] NS
0x004004e9  [   5, 0] NS
0x004004ec  [   7, 0] NS
0x004004f0  [   9, 0] NS DI=0x1
0x004004fa  [  10, 0] NS DI=0x1
0x004004fc  [  10, 0] NS ET

IIUC, 0x004004fa corresponds to line 10 (the ending brace for the while loop).

Without the change, find_address(0x004004fa) will return end() instead of the entry. See whole program at https://paste.ubuntu.com/p/24F7N6jSyN/.

Does it mean the end sequence is missing, or do I get anything wrong?

@aclements
Copy link
Owner

I'm not sure how to interpret that line number table dump you pasted. It looks like it's already been rather processed, which makes it hard to tell what's going on at a low level. The "ET" on the last line suggests there is an end_sequence. Can you post a more raw dump, for example from objdump --dwarf=rawline?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants