-
Notifications
You must be signed in to change notification settings - Fork 570
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
Split segments and record segment offsets. #2940
Split segments and record segment offsets. #2940
Conversation
This change changes the modules.log format to provide a separate entry for each segment instead of combining entries for contiguous segments mapped from each image. The module file version is incremented to 4 and adds a new field called offseti after the "entry" field. The file offset information for unix is recorded in module_add_segment_data and propagated to drmodtrack to be written out with each segment.
Do not set the offset field for WINDOWS.
ext/drcovlib/drcovlib.h
Outdated
@@ -249,6 +249,10 @@ typedef struct _drmodtrack_info_t { | |||
* passed to drmodtrack_offline_lookup(). | |||
*/ | |||
uint index; | |||
/** | |||
* The offset of this segment from the beginnig of this backing file. |
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.
"beginning"
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.
Done.
@@ -539,7 +539,8 @@ module_walk_program_headers(app_pc base, size_t view_size, bool at_map, bool dyn | |||
(app_pc) prog_hdr->p_vaddr + load_delta, | |||
prog_hdr->p_memsz, | |||
module_segment_prot_to_osprot(prog_hdr), | |||
prog_hdr->p_align, false/*!shared*/); | |||
prog_hdr->p_align, false/*!shared*/, | |||
prog_hdr->p_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.
The call in module_macho.c needs to be updated as well. We removed Mac from Travis on PR's because the delay was too long to get a machine but it does run post-commit to master and this will fail to build there.
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.
Done.
@@ -2918,6 +2918,7 @@ typedef struct _module_segment_data_t { | |||
app_pc start; /**< Start address of the segment, page-aligned backward. */ | |||
app_pc end; /**< End address of the segment, page-aligned forward. */ | |||
uint prot; /**< Protection attributes of the segment */ | |||
uint64 offset; /**< Offset of the segment from the beginning of the backing file */ |
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.
(We allocate this struct, so appending to the end should be fine compatibility-wise.)
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.
Acknowledged.
ext/drcovlib/modules.c
Outdated
if (dr_sscanf(buf, "%u, %u, "PIFX", "PIFX", "PIFX", ", | ||
&mod_id, &info->mod[i].containing_id, | ||
&info->mod[i].base, &end, &info->mod[i].entry) != 5 || | ||
mod_id != i) | ||
goto read_error; | ||
buf = skip_commas_and_spaces(buf, 5); | ||
} else { // version == 4 | ||
if (dr_sscanf(buf, "%u, %u, "PIFX", "PIFX", "PIFX", "PIFX", ", |
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.
This is the wrong scanf type: PIFX
is pointer-sized so for 32-bit it will be 32 bits. Use HEX64_FORMAT_STRING
.
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.
Done.
ext/drcovlib/modules.c
Outdated
@@ -725,6 +734,7 @@ drmodtrack_offline_lookup(void *handle, uint index, OUT drmodtrack_info_t *out) | |||
out->timestamp = info->mod[index].timestamp; | |||
#endif | |||
out->custom = info->mod[index].custom; | |||
out->offset = info->mod[index].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.
This will overflow and corrupt memory for clients using the older struct. Use a struct_size compatibility check like the one below for index (seems good to move it down below the index set as well to keep it in order).
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.
Done.
if (dr_sscanf(buf, "%u, %u, "PIFX", "PIFX", "PIFX", ", | ||
&mod_id, &info->mod[i].containing_id, | ||
&info->mod[i].base, &end, &info->mod[i].entry) != 5 || | ||
mod_id != i) | ||
goto read_error; | ||
buf = skip_commas_and_spaces(buf, 5); | ||
} else { // version == 4 |
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.
Bug: removing the else from the 3 above means version 2 will enter here -- seems best to have the if for 3 be an else if.
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.
Done.
ext/drcovlib/modules.c
Outdated
@@ -466,6 +461,11 @@ module_table_entry_print(module_entry_t *entry, char *buf, size_t size) | |||
#endif | |||
read_entry.path = full_path; | |||
read_entry.custom = entry->custom; | |||
#ifndef WINDOWS | |||
// For unices we record the physical offset from the backing file. Each | |||
// module entry only has a sigle segment so we grab index 0 of the array. |
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.
"single"
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.
Done.
ext/drcovlib/modules.c
Outdated
@@ -413,9 +408,9 @@ static int | |||
module_read_entry_print(module_read_entry_t *entry, uint idx, char *buf, size_t size) | |||
{ | |||
int len, total_len = 0; | |||
len = dr_snprintf(buf, size, "%3u, %3u, " PFX ", " PFX ", " PFX ", ", | |||
len = dr_snprintf(buf, size, "%3u, %3u, " PFX ", " PFX ", " PFX ", " PFX ", ", |
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.
PFX
is the wrong code: it is pointer-sized while offset is always 64 bits. Use ZHEX64_FORMAT_STRING
.
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.
Done.
ext/drcovlib/modules.c
Outdated
#ifndef WINDOWS | ||
// For unices we record the physical offset from the backing file. Each | ||
// module entry only has a sigle segment so we grab index 0 of the array. | ||
read_entry.offset = entry->data->segments[0].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.
I don't think this is correct: entry->data points at DR's module_data_t and each segment entry here points at the same data structure. module_entry_t
needs to store either the offset or the segment index (or I guess you could compute the segment index here by assuming they're contiguous and in order).
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.
Done.
ext/drcovlib/modules.c
Outdated
#ifndef WINDOWS | ||
// For unices we record the physical offset from the backing file. Each | ||
// module entry only has a sigle segment so we grab index 0 of the array. | ||
read_entry.offset = entry->data->segments[0].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.
Maybe it's worth adding code to suite/tests/client-interface/drmodtrack-test.dll.cpp
to test that the offsets match the DR fields (or even better the /proc/self/maps fields on Linux but that is more work).
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'm unsure what is implied by "match the DR fields". For example I can get info.offset here (after checking info.struct_size) --
https://github.com/DynamoRIO/dynamorio/blob/master/suite/tests/client-interface/drmodtrack-test.dll.cpp#L134
but I don't understand what I can compare it with (apart from parsing proc/self/maps)?
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 mean using DR's module list while the process is live here to get module info and compare it to drmodtrack's: e.g., using dr_module_iterator_start() or dr_lookup_module().
@@ -1811,6 +1811,7 @@ create_and_initialize_module_data(app_pc start, app_pc end, app_pc entry_point, | |||
copy->segments[i].start = os_segments[i].start; |
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.
Also, please add a feature entry to https://github.com/DynamoRIO/dynamorio/blob/master/api/docs/release.dox#L230
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.
Done.
Fixed issues.
Updated documentation.
run arm tests |
Extend the test in client-interface/drmodtrack-test.dll.cpp to check whether the offset recorded by drmodtrack match the offset for the segment in DRs module data. Also fixed lint issue.
Fix test failure on Windows where the struct fields for segments don't exist.
I've added the test, fixed lint issues and fixed the build issue for Windows. Please take another look. Thanks. |
add to whitelist |
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.
Just some style nits
api/docs/release.dox
Outdated
@@ -229,6 +229,8 @@ Further non-compatibility-affecting changes include: | |||
of built basic blocks. | |||
- Added drreg_reservation_info_ex(), drreg_statelessly_restore_app_value(), | |||
and drreg_is_instr_spill_or_restore(). | |||
- Module tracking allocates an entry per segment for each loaded module. |
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.
Please include drmodtrack
so we know which library/component this is: the core API provides module information as well.
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.
Done.
api/docs/release.dox
Outdated
@@ -229,6 +229,8 @@ Further non-compatibility-affecting changes include: | |||
of built basic blocks. | |||
- Added drreg_reservation_info_ex(), drreg_statelessly_restore_app_value(), | |||
and drreg_is_instr_spill_or_restore(). | |||
- Module tracking allocates an entry per segment for each loaded module. | |||
File offsets for each segment are recorded in modules.log. |
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.
Please include drcachesim
(and UNIX) to give context on which tool/component this is referring to.
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.
Done.
api/docs/release.dox
Outdated
@@ -229,6 +229,8 @@ Further non-compatibility-affecting changes include: | |||
of built basic blocks. | |||
- Added drreg_reservation_info_ex(), drreg_statelessly_restore_app_value(), | |||
and drreg_is_instr_spill_or_restore(). | |||
- Module tracking allocates an entry per segment for each loaded module. | |||
File offsets for each segment are recorded in modules.log. |
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.
Please also mention that #module_segment_data_t
now includes the file offset on UNIX.
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.
Done.
@@ -132,6 +133,19 @@ event_exit(void) | |||
CHECK(((app_pc)info.custom) == info.start || | |||
info.containing_index != i, "custom field doesn't match"); | |||
CHECK(info.index == i, "index field doesn't match"); | |||
#ifndef WINDOWS | |||
if(info.struct_size > offsetof(drmodtrack_info_t, 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.
style: if (
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.
Done.
#ifndef WINDOWS | ||
if(info.struct_size > offsetof(drmodtrack_info_t, offset)) { | ||
module_data_t * data = dr_lookup_module(info.start); | ||
for(uint j = 0; j < data->num_segments; j++) { |
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.
style: for (
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.
Done.
module_data_t * data = dr_lookup_module(info.start); | ||
for(uint j = 0; j < data->num_segments; j++) { | ||
module_segment_data_t *seg = data->segments + j; | ||
if(seg->start == info.start) { |
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.
style: if (
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.
Done.
module_segment_data_t *seg = data->segments + j; | ||
if(seg->start == info.start) { | ||
CHECK(seg->offset == info.offset, | ||
"Module data offset and drmodtrack offset don't match"); |
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.
style nit: Indent looks off (should line up with seg
after the paren.)
ext/drcovlib/modules.c
Outdated
@@ -663,13 +669,23 @@ drmodtrack_offline_read(file_t file, const char *map, OUT const char **next_line | |||
goto read_error; | |||
info->mod[i].containing_id = mod_id; | |||
buf = skip_commas_and_spaces(buf, 4); | |||
} else { | |||
} | |||
else if (version == 3) { |
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.
minor nit: since already changing some other things I would suggest putting the else on the prior line for consistency w/ the surrounding if-else chains
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.
Done.
Updated release docs and fixed style issues.
…h/dynamorio into i2939-phys-offset-split-segment
This reverts commit 48db566 which reverted the changes in PR DynamoRIO#2940. The changes pushed caused some apps to overflow the modidx field (issue DynamoRIO#2956). PR DynamoRIO#2969 increased the width of the modidx field. We can now safely revert the revert.
PR #2940 and #2973 added an offset field to drmodtrack for #2939, but they ifdef-ed the field in some places but not others, resulting in uninitialized output. Since it's already locked into the interface, we always set it to 0 here and include it in internal structures to fix the problem. Tested on drmodtrack-test where the fields were manually confirmed to no longer contain bogus values, and where the test doesn't fail when that masked this bug before. Issue: #2939, #4474, #4777 Fixes #4777
PR #2940 and #2973 added an offset field to drmodtrack for #2939, but they ifdef-ed the field in some places but not others, resulting in uninitialized output. Since it's already locked into the interface, we always set it to 0 here and include it in internal structures to fix the problem. Tested on drmodtrack-test where the fields were manually confirmed to no longer contain bogus values, and where the test doesn't fail when that masked this bug before. Issue: #2939, #4474, #4777 Fixes #4777
PR #2940 and #2973 added an offset field to drmodtrack for #2939, but they ifdef-ed the field in some places but not others, resulting in uninitialized output. Since it's already locked into the interface, we always set it to 0 here and include it in internal structures to fix the problem. Tested on drmodtrack-test where the fields were manually confirmed to no longer contain bogus values, and where the test doesn't fail when i#4474 adds a new field that shifts the test buffer to avoid the happens-to-match scenario that masked this bug in that test before. Issue: #2939, #4474, #4777 Fixes #4777
This change changes the modules.log format to provide a separate entry
for each segment instead of combining entries for contiguous segments
mapped from each image. The module file version is incremented to 4 and
adds a new field called offseti after the "entry" field.
The file offset information for unix is recorded in
module_add_segment_data and propagated to drmodtrack to be written out
with each segment.