Index: courgette/disassembler_win32_x64.cc |
diff --git a/courgette/disassembler_win32_x64.cc b/courgette/disassembler_win32_x64.cc |
index ffa6c36a7aade5f0d7954149fc11bc667b91543c..2db35a39d8a103f8f9fa75b6ddf403e7af6f7edc 100644 |
--- a/courgette/disassembler_win32_x64.cc |
+++ b/courgette/disassembler_win32_x64.cc |
@@ -252,6 +252,9 @@ bool DisassemblerWin32X64::Disassemble(AssemblyProgram* target) { |
ParseRel32RelocsFromSections(); |
+ PrecomputeLabels(target); |
+ RemoveUnusedRel32Locations(target); |
+ |
if (!ParseFile(target)) |
return false; |
@@ -357,6 +360,26 @@ std::string DisassemblerWin32X64::SectionName(const Section* section) { |
return name; |
} |
+RvaVisitor* DisassemblerWin32X64::CreateAbs32TargetRvaVisitor() { |
+ return new RvaVisitor_Abs32(abs32_locations_, *this); |
+} |
+ |
+RvaVisitor* DisassemblerWin32X64::CreateRel32TargetRvaVisitor() { |
+ return new RvaVisitor_Rel32(rel32_locations_, *this); |
+} |
+ |
+void DisassemblerWin32X64::RemoveUnusedRel32Locations( |
+ AssemblyProgram* program) { |
+ auto cond = [this, program](RVA rva) -> bool { |
+ // + 4 since offset is relative to start of next instruction. |
+ RVA target_rva = rva + 4 + Read32LittleEndian(RVAToPointer(rva)); |
+ return program->FindRel32Label(target_rva) == nullptr; |
+ }; |
+ rel32_locations_.erase( |
+ std::remove_if(rel32_locations_.begin(), rel32_locations_.end(), cond), |
+ rel32_locations_.end()); |
+} |
+ |
CheckBool DisassemblerWin32X64::ParseFile(AssemblyProgram* program) { |
// Walk all the bytes in the file, whether or not in a section. |
FileOffset file_offset = 0; |
@@ -525,12 +548,13 @@ void DisassemblerWin32X64::ParseRel32RelocsFromSection(const Section* section) { |
if (abs32_pos != abs32_locations_.end()) { |
if (*abs32_pos < rel32_rva + 4) { |
// Beginning of abs32 reloc is before end of rel32 reloc so they |
- // overlap. Skip four bytes past the abs32 reloc. |
+ // overlap. Skip four bytes past the abs32 reloc. |
p += (*abs32_pos + 4) - current_rva; |
continue; |
} |
} |
+ // + 4 since offset is relative to start of next instruction. |
RVA target_rva = rel32_rva + 4 + Read32LittleEndian(rel32); |
// To be valid, rel32 target must be within image, and within this |
// section. |
@@ -614,7 +638,9 @@ CheckBool DisassemblerWin32X64::ParseFileRegion(const Section* section, |
DCHECK_NE(kNoRVA, target_rva); |
// TODO(sra): target could be Label+offset. It is not clear how to guess |
// which it might be. We assume offset==0. |
- if (!program->EmitAbs64(program->FindOrMakeAbs32Label(target_rva))) |
+ Label* label = program->FindAbs32Label(target_rva); |
+ DCHECK(label); |
+ if (!program->EmitAbs64(label)) |
return false; |
p += 8; |
continue; |
@@ -624,8 +650,11 @@ CheckBool DisassemblerWin32X64::ParseFileRegion(const Section* section, |
++rel32_pos; |
if (rel32_pos != rel32_locations_.end() && *rel32_pos == current_rva) { |
+ // + 4 since offset is relative to start of next instruction. |
RVA target_rva = current_rva + 4 + Read32LittleEndian(p); |
- if (!program->EmitRel32(program->FindOrMakeRel32Label(target_rva))) |
+ Label* label = program->FindRel32Label(target_rva); |
+ DCHECK(label); |
+ if (!program->EmitRel32(label)) |
return false; |
p += 4; |
continue; |