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

Address returned by read_address() doesn't match with the one in objdump of object file #548

Closed
vaibspider opened this issue Feb 6, 2021 · 7 comments

Comments

@vaibspider
Copy link
Contributor

Hi,
I am reading a relocatable object file, to get a location list at a particular offset and I'm using this ReaderRelocate implementation: https://github.com/philipc/rewrite/blob/master/src/dwarf.rs#L363. I'm trying to read existing location list, add a new entry there and then update the object file with the newly created location list.

I see that ReaderRelocate::read_address() uses a Vec<write::Address> and returns an index into this Vec, instead of the actual address value.
But, somehow, when I am reading begin and end addresses in a location list at a particular offset, it's showing a different address, as compared to one shown by objdump of the object file.

Could you please suggest something?
Thanks!

@philipc
Copy link
Collaborator

philipc commented Feb 7, 2021

Can you give me steps for how to reproduce the issue?

@vaibspider
Copy link
Contributor Author

vaibspider commented Feb 7, 2021

Sure.
I am working with this object file - bzip2.o and I am looking at variable zz inside the UPHEAP function.
First, I am traversing the DIEs, to reach at function UPHEAP and when I see the variable zz, I am printing the address ranges inside its location list (using gimli::read::Dwarf APIs, before converting it into gimli::write::Dwarf). It is showing the output as follows:
output1:-

Entry tag: Some("DW_TAG_variable") 
Index : 0 
location lists offset: LocationListsOffset(252)
loc range: Range { begin: 130, end: 131 }            
loc range: Range { begin: 132, end: 133 } 
loc range: Range { begin: 134, end: 135 }
Name: zz

But, when I look into the objdump of the same object file, I get the following location list:
output2:-

    000000fc 000004b6 000004bd (DW_OP_breg4 (esp): 12)
    00000108 000004bd 000004cd (DW_OP_reg2 (edx))
    00000113 000004e9 000004eb (DW_OP_reg2 (edx))

We can see that the LocationListsOffset(252) from output1 is indeed the one present in the location list from output2 - 0xfc.
And as we are using ReadAddressMap to store addresses, I expect that the locations 130..135 in output1 should point to the addresses 4b6..4eb in output2.
But, they seem to be pointing to the addresses 43e..490, when I print the ReadAddressMap(after converting gimli::read::Dwarf to gimli::write::Dwarf)
Also, if I try to get the mapping of the key 130 in ReadAddressMap, while printing the ranges in output1 above, it shows an error - indicating that the map only has around 68 entries in it.

Could you please have a look at it?
Thanks!

@philipc
Copy link
Collaborator

philipc commented Feb 7, 2021

Sure, might be a few days though. Let me know if you fix the problem before then.

@philipc
Copy link
Collaborator

philipc commented Feb 8, 2021

Using philipc/rewrite@9d3e948, I get

input:

    000000fc 000004b6 000004bd (DW_OP_breg4 (esp): 12)
    00000108 000004bd 000004cd (DW_OP_reg2 (edx))
    00000113 000004e9 000004eb (DW_OP_reg2 (edx))
    0000011e <End of list>

output:

    00000123 000004b6 000004bd (DW_OP_breg4 (esp): 12)
    0000012f 000004bd 000004cd (DW_OP_reg2 (edx))
    0000013a 000004e9 000004eb (DW_OP_reg2 (edx))
    00000145 <End of list>

This looks correct to me, so you need to give me more information on how to reproduce this problem.

@vaibspider
Copy link
Contributor Author

Oh, I see. Thanks!
I was getting different value, when I print it while iterating over the location lists, before converting read::Dwarf to write::Dwarf, like below:

let mut loclist_iter = dwarf.locations(&unit, location_lists_offset).unwrap();
while let Some(loclist_entry) = loclist_iter.next().unwrap() {
    eprintln!("loc range: {:?}", loclist_entry.range);
}

Looking at your output, I thought there might be something that is being added to the original value of the range.
So I debugged through the calls to loclist_iter.next() inside gimli and I found that a base address is being added to the range of an location entry, if it was AddressOrOffsetPair:-

RawLocListEntry::AddressOrOffsetPair { begin, end, data }                                                                             
| RawLocListEntry::OffsetPair { begin, end, data } => { 
    let mut range = Range { begin, end };
    range.add_base_address(self.base_address, self.raw.encoding.address_size);
    (range, data)
}

I found that this base_address is coming from unit.low_pc, whose value was non-zero, as it was representing an index into the ReadAddressMap.
Now, for using the range of a location list entry, I will have to subtract this base_address to get the correct index into the ReadAddressMap.

The issue is resolved now. Thanks for your help! I couldn't figure it out earlier.

@philipc
Copy link
Collaborator

philipc commented Feb 11, 2021

Ah that makes sense. Another option would be to use the raw location lists instead (that's what rewrite is doing). Sounds like we really do need to implement #409 to avoid this sort of problem.

@vaibspider
Copy link
Contributor Author

Ok, yes, I see. This problem wouldn't occur if I use the raw location lists. But, yeah, implementing the Reader::Address might be helpful.

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

No branches or pull requests

2 participants