Skip to content

Commit

Permalink
[Courgette] Fix ELF reference sorting.
Browse files Browse the repository at this point in the history
This CL addresses 2 reference sorting issues in DisassemblerElf32:

(1) Bug fix: In ParseFile(), |abs32_locations_| (RVAs) is translated to
    |abs_offsets| (file offsets), but we sort |abs32_locations_|, which
    is redundant. Actually we should sort |abs_offsets|.
(2) Cleanup: |rel32_relocations_| stores rel32 references sorted by
    RVA, but in ParseFile() we re-sort these in offset order. Previously
    Disassemble() optimizes away redundant sorts, but this makes the
    code less robust. We de-optimize this a little potentially redundant
    sort-by-RVA, to assert that |rel32_locations_| is sorted by RVA
    outside of ParseFile().

This CL also makes Disassemble() more uniform, to prepare for
refactoring in a follow-up. Meanwhile, DisassemblerWin32 does not
experience issue since it assumes RVA order is same as file offset
order (this assumption has not has not caused problems so far).

BUG=660980

Review-Url: https://codereview.chromium.org/2744373004
Cr-Commit-Position: refs/heads/master@{#458650}
  • Loading branch information
samuelhuang authored and Commit bot committed Mar 22, 2017
1 parent ba7b76c commit c615c91
Showing 1 changed file with 16 additions and 11 deletions.
27 changes: 16 additions & 11 deletions courgette/disassembler_elf_32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,6 @@ bool DisassemblerElf32::Disassemble(AssemblyProgram* program) {
return false;
}

// Finally sort rel32 locations.
std::sort(rel32_locations_.begin(),
rel32_locations_.end(),
TypedRVA::IsLessThanByRVA);
DCHECK(rel32_locations_.empty() ||
rel32_locations_.back()->rva() != kUnassignedRVA);

program->DefaultAssignIndexes();
return true;
}
Expand Down Expand Up @@ -384,6 +377,11 @@ CheckBool DisassemblerElf32::ParseRel32RelocsFromSections() {
if (!found_rel32)
VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?";

std::sort(rel32_locations_.begin(), rel32_locations_.end(),
TypedRVA::IsLessThanByRVA);
DCHECK(rel32_locations_.empty() ||
rel32_locations_.back()->rva() != kUnassignedRVA);

return true;
}

Expand Down Expand Up @@ -418,15 +416,18 @@ CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program,
// Walk all the bytes in the file, whether or not in a section.
FileOffset file_offset = 0;

std::vector<FileOffset> abs_offsets;

// File parsing follows file offset order, and we visit abs32 and rel32
// locations in lockstep. Therefore we need to extract and sort file offsets
// of all abs32 and rel32 locations.
// of all abs32 and rel32 locations. For abs32, we copy the offsets to a new
// array.
std::vector<FileOffset> abs_offsets;
if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets))
return false;
std::sort(abs32_locations_.begin(), abs32_locations_.end());
std::sort(abs_offsets.begin(), abs_offsets.end());

// For rel32, TypedRVA (rather than raw offset) is stored, so sort-by-offset
// is performed in place to save memory. At the end of function we will
// sort-by-RVA.
if (!RVAsToFileOffsets(&rel32_locations_))
return false;
std::sort(rel32_locations_.begin(),
Expand Down Expand Up @@ -496,6 +497,10 @@ CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program,
if (!ParseSimpleRegion(file_offset, length(), receptor))
return false;

// Restore original rel32 location order and sort by RVA order.
std::sort(rel32_locations_.begin(), rel32_locations_.end(),
TypedRVA::IsLessThanByRVA);

// Make certain we consume all of the relocations as expected
return (current_abs_offset == end_abs_offset);
}
Expand Down

0 comments on commit c615c91

Please sign in to comment.