Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Unified Diff: courgette/disassembler_elf_32.cc

Issue 1935203002: [Courgette] Using LabelManager to reduce Courgette-apply peak RAM by 25%. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: courgette/disassembler_elf_32.cc
diff --git a/courgette/disassembler_elf_32.cc b/courgette/disassembler_elf_32.cc
index 6285c3878170f4c2f7371b43282432b8fde688da..4809391fb3bfc59def1ef654d4f04a4169df6f72 100644
--- a/courgette/disassembler_elf_32.cc
+++ b/courgette/disassembler_elf_32.cc
@@ -32,6 +32,15 @@ std::vector<Elf32_Half> GetSectionHeaderFileOffsetOrder(
} // namespace
+DisassemblerElf32::Elf32RvaVisitor_Rel32::Elf32RvaVisitor_Rel32(
+ const std::vector<TypedRVA*>& rva_locations)
+ : VectorRvaVisitor<TypedRVA*>(rva_locations) {
+}
+
+RVA DisassemblerElf32::Elf32RvaVisitor_Rel32::Get() const {
+ return (*it_)->rva() + (*it_)->relative_target();
+}
+
DisassemblerElf32::DisassemblerElf32(const void* start, size_t length)
: Disassembler(start, length),
header_(nullptr),
@@ -163,12 +172,16 @@ bool DisassemblerElf32::Disassemble(AssemblyProgram* target) {
if (!ParseAbs32Relocs())
return false;
- if (!ParseRel32RelocsFromSections())
+ if (!ParseRel32RelocsFromSections()) // Does not sort rel32 locations.
return false;
+ PrecomputeLabels(target);
+ RemoveUnusedRel32Locations(target);
+
if (!ParseFile(target))
return false;
+ // Finally sort rel32 locations.
std::sort(rel32_locations_.begin(),
rel32_locations_.end(),
TypedRVA::IsLessThanByRVA);
@@ -179,6 +192,28 @@ bool DisassemblerElf32::Disassemble(AssemblyProgram* target) {
return true;
}
+CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const {
+ if (rva == kUnassignedRVA)
+ return false;
+
+ // |rva| is valid if it's contained in any program segment.
+ for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
+ ++segment_id) {
+ const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
+
+ if (segment_header->p_type != PT_LOAD)
+ continue;
+
+ Elf32_Addr begin = segment_header->p_vaddr;
+ Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
+
+ if (rva >= begin && rva < end)
+ return true;
+ }
+
+ return false;
+}
+
bool DisassemblerElf32::UpdateLength() {
Elf32_Off result = 0;
@@ -237,32 +272,11 @@ CheckBool DisassemblerElf32::SectionName(const Elf32_Shdr& shdr,
return true;
}
-CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const {
- if (rva == kUnassignedRVA)
- return false;
-
- // It's valid if it's contained in any program segment
- for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
- ++segment_id) {
- const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
-
- if (segment_header->p_type != PT_LOAD)
- continue;
-
- Elf32_Addr begin = segment_header->p_vaddr;
- Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
-
- if (rva >= begin && rva < end)
- return true;
- }
-
- return false;
-}
-
CheckBool DisassemblerElf32::RVAsToFileOffsets(
const std::vector<RVA>& rvas,
std::vector<FileOffset>* file_offsets) {
file_offsets->clear();
+ file_offsets->reserve(rvas.size());
for (RVA rva : rvas) {
FileOffset file_offset = RVAToFileOffset(rva);
if (file_offset == kNoFileOffset)
@@ -283,6 +297,24 @@ CheckBool DisassemblerElf32::RVAsToFileOffsets(
return true;
}
+RvaVisitor* DisassemblerElf32::CreateAbs32TargetRvaVisitor() {
+ return new RvaVisitor_Abs32(abs32_locations_, *this);
+}
+
+RvaVisitor* DisassemblerElf32::CreateRel32TargetRvaVisitor() {
+ return new Elf32RvaVisitor_Rel32(rel32_locations_.get());
+}
+
+void DisassemblerElf32::RemoveUnusedRel32Locations(AssemblyProgram* program) {
+ auto cond = [program](const TypedRVA* typed_rva) -> bool {
+ RVA target_rva = typed_rva->rva() + typed_rva->relative_target();
+ return program->FindRel32Label(target_rva) == nullptr;
+ };
+ rel32_locations_.erase(
+ std::remove_if(rel32_locations_.begin(), rel32_locations_.end(), cond),
+ rel32_locations_.end());
+}
+
CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) {
// Walk all the bytes in the file, whether or not in a section.
FileOffset file_offset = 0;
@@ -422,7 +454,9 @@ CheckBool DisassemblerElf32::ParseProgbitsSection(
RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset));
DCHECK_NE(kNoRVA, target_rva);
- if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva)))
+ Label* label = program->FindAbs32Label(target_rva);
+ CHECK(label);
+ if (!program->EmitAbs32(label))
return false;
file_offset += sizeof(RVA);
++(*current_abs_offset);
@@ -432,12 +466,17 @@ CheckBool DisassemblerElf32::ParseProgbitsSection(
if (*current_rel != end_rel &&
file_offset == (**current_rel)->file_offset()) {
uint32_t relative_target = (**current_rel)->relative_target();
+ CHECK_EQ(RVA(origin + (file_offset - origin_offset)),
+ (**current_rel)->rva());
// This cast is for 64 bit systems, and is only safe because we
// are working on 32 bit executables.
RVA target_rva = (RVA)(origin + (file_offset - origin_offset) +
relative_target);
- if (!(**current_rel)->EmitInstruction(program, target_rva))
+ Label* label = program->FindRel32Label(target_rva);
+ CHECK(label);
+
+ if (!(**current_rel)->EmitInstruction(program, label))
return false;
file_offset += (**current_rel)->op_size();
++(*current_rel);

Powered by Google App Engine
This is Rietveld 408576698