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

Side by Side 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, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "courgette/disassembler_elf_32.h" 5 #include "courgette/disassembler_elf_32.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "courgette/assembly_program.h" 10 #include "courgette/assembly_program.h"
(...skipping 14 matching lines...) Expand all
25 25
26 auto comp = [&](int idx1, int idx2) { 26 auto comp = [&](int idx1, int idx2) {
27 return section_headers[idx1].sh_offset < section_headers[idx2].sh_offset; 27 return section_headers[idx1].sh_offset < section_headers[idx2].sh_offset;
28 }; 28 };
29 std::stable_sort(order.begin(), order.end(), comp); 29 std::stable_sort(order.begin(), order.end(), comp);
30 return order; 30 return order;
31 } 31 }
32 32
33 } // namespace 33 } // namespace
34 34
35 DisassemblerElf32::Elf32RvaVisitor_Rel32::Elf32RvaVisitor_Rel32(
36 const std::vector<TypedRVA*>& rva_locations)
37 : VectorRvaVisitor<TypedRVA*>(rva_locations) {
38 }
39
40 RVA DisassemblerElf32::Elf32RvaVisitor_Rel32::Get() const {
41 return (*it_)->rva() + (*it_)->relative_target();
42 }
43
35 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length) 44 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length)
36 : Disassembler(start, length), 45 : Disassembler(start, length),
37 header_(nullptr), 46 header_(nullptr),
38 section_header_table_size_(0), 47 section_header_table_size_(0),
39 program_header_table_(nullptr), 48 program_header_table_(nullptr),
40 program_header_table_size_(0), 49 program_header_table_size_(0),
41 default_string_section_(nullptr) { 50 default_string_section_(nullptr) {
42 } 51 }
43 52
44 RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const { 53 RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const {
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) { 165 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) {
157 if (!ok()) 166 if (!ok())
158 return false; 167 return false;
159 168
160 // The Image Base is always 0 for ELF Executables 169 // The Image Base is always 0 for ELF Executables
161 target->set_image_base(0); 170 target->set_image_base(0);
162 171
163 if (!ParseAbs32Relocs()) 172 if (!ParseAbs32Relocs())
164 return false; 173 return false;
165 174
166 if (!ParseRel32RelocsFromSections()) 175 if (!ParseRel32RelocsFromSections()) // Does not sort rel32 locations.
167 return false; 176 return false;
168 177
178 PrecomputeLabels(target);
179 RemoveUnusedRel32Locations(target);
180
169 if (!ParseFile(target)) 181 if (!ParseFile(target))
170 return false; 182 return false;
171 183
184 // Finally sort rel32 locations.
172 std::sort(rel32_locations_.begin(), 185 std::sort(rel32_locations_.begin(),
173 rel32_locations_.end(), 186 rel32_locations_.end(),
174 TypedRVA::IsLessThanByRVA); 187 TypedRVA::IsLessThanByRVA);
175 DCHECK(rel32_locations_.empty() || 188 DCHECK(rel32_locations_.empty() ||
176 rel32_locations_.back()->rva() != kUnassignedRVA); 189 rel32_locations_.back()->rva() != kUnassignedRVA);
177 190
178 target->DefaultAssignIndexes(); 191 target->DefaultAssignIndexes();
179 return true; 192 return true;
180 } 193 }
181 194
195 CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const {
196 if (rva == kUnassignedRVA)
197 return false;
198
199 // |rva| is valid if it's contained in any program segment.
200 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
201 ++segment_id) {
202 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
203
204 if (segment_header->p_type != PT_LOAD)
205 continue;
206
207 Elf32_Addr begin = segment_header->p_vaddr;
208 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
209
210 if (rva >= begin && rva < end)
211 return true;
212 }
213
214 return false;
215 }
216
182 bool DisassemblerElf32::UpdateLength() { 217 bool DisassemblerElf32::UpdateLength() {
183 Elf32_Off result = 0; 218 Elf32_Off result = 0;
184 219
185 // Find the end of the last section 220 // Find the end of the last section
186 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); 221 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
187 ++section_id) { 222 ++section_id) {
188 const Elf32_Shdr* section_header = SectionHeader(section_id); 223 const Elf32_Shdr* section_header = SectionHeader(section_id);
189 224
190 if (section_header->sh_type == SHT_NOBITS) 225 if (section_header->sh_type == SHT_NOBITS)
191 continue; 226 continue;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 name->clear(); 265 name->clear();
231 } else { 266 } else {
232 if (string_pos >= default_string_section_size_) 267 if (string_pos >= default_string_section_size_)
233 return false; 268 return false;
234 // Safe because string section must terminate with null. 269 // Safe because string section must terminate with null.
235 *name = default_string_section_ + string_pos; 270 *name = default_string_section_ + string_pos;
236 } 271 }
237 return true; 272 return true;
238 } 273 }
239 274
240 CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const {
241 if (rva == kUnassignedRVA)
242 return false;
243
244 // It's valid if it's contained in any program segment
245 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
246 ++segment_id) {
247 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
248
249 if (segment_header->p_type != PT_LOAD)
250 continue;
251
252 Elf32_Addr begin = segment_header->p_vaddr;
253 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
254
255 if (rva >= begin && rva < end)
256 return true;
257 }
258
259 return false;
260 }
261
262 CheckBool DisassemblerElf32::RVAsToFileOffsets( 275 CheckBool DisassemblerElf32::RVAsToFileOffsets(
263 const std::vector<RVA>& rvas, 276 const std::vector<RVA>& rvas,
264 std::vector<FileOffset>* file_offsets) { 277 std::vector<FileOffset>* file_offsets) {
265 file_offsets->clear(); 278 file_offsets->clear();
279 file_offsets->reserve(rvas.size());
266 for (RVA rva : rvas) { 280 for (RVA rva : rvas) {
267 FileOffset file_offset = RVAToFileOffset(rva); 281 FileOffset file_offset = RVAToFileOffset(rva);
268 if (file_offset == kNoFileOffset) 282 if (file_offset == kNoFileOffset)
269 return false; 283 return false;
270 file_offsets->push_back(file_offset); 284 file_offsets->push_back(file_offset);
271 } 285 }
272 return true; 286 return true;
273 } 287 }
274 288
275 CheckBool DisassemblerElf32::RVAsToFileOffsets( 289 CheckBool DisassemblerElf32::RVAsToFileOffsets(
276 ScopedVector<TypedRVA>* typed_rvas) { 290 ScopedVector<TypedRVA>* typed_rvas) {
277 for (TypedRVA* typed_rva : *typed_rvas) { 291 for (TypedRVA* typed_rva : *typed_rvas) {
278 FileOffset file_offset = RVAToFileOffset(typed_rva->rva()); 292 FileOffset file_offset = RVAToFileOffset(typed_rva->rva());
279 if (file_offset == kNoFileOffset) 293 if (file_offset == kNoFileOffset)
280 return false; 294 return false;
281 typed_rva->set_file_offset(file_offset); 295 typed_rva->set_file_offset(file_offset);
282 } 296 }
283 return true; 297 return true;
284 } 298 }
285 299
300 RvaVisitor* DisassemblerElf32::CreateAbs32TargetRvaVisitor() {
301 return new RvaVisitor_Abs32(abs32_locations_, *this);
302 }
303
304 RvaVisitor* DisassemblerElf32::CreateRel32TargetRvaVisitor() {
305 return new Elf32RvaVisitor_Rel32(rel32_locations_.get());
306 }
307
308 void DisassemblerElf32::RemoveUnusedRel32Locations(AssemblyProgram* program) {
309 auto cond = [program](const TypedRVA* typed_rva) -> bool {
310 RVA target_rva = typed_rva->rva() + typed_rva->relative_target();
311 return program->FindRel32Label(target_rva) == nullptr;
312 };
313 rel32_locations_.erase(
314 std::remove_if(rel32_locations_.begin(), rel32_locations_.end(), cond),
315 rel32_locations_.end());
316 }
317
286 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) { 318 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) {
287 // Walk all the bytes in the file, whether or not in a section. 319 // Walk all the bytes in the file, whether or not in a section.
288 FileOffset file_offset = 0; 320 FileOffset file_offset = 0;
289 321
290 std::vector<FileOffset> abs_offsets; 322 std::vector<FileOffset> abs_offsets;
291 323
292 // File parsing follows file offset order, and we visit abs32 and rel32 324 // File parsing follows file offset order, and we visit abs32 and rel32
293 // locations in lockstep. Therefore we need to extract and sort file offsets 325 // locations in lockstep. Therefore we need to extract and sort file offsets
294 // of all abs32 and rel32 locations. 326 // of all abs32 and rel32 locations.
295 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets)) 327 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets))
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 447
416 file_offset = next_relocation; 448 file_offset = next_relocation;
417 continue; 449 continue;
418 } 450 }
419 451
420 if (*current_abs_offset != end_abs_offset && 452 if (*current_abs_offset != end_abs_offset &&
421 file_offset == **current_abs_offset) { 453 file_offset == **current_abs_offset) {
422 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset)); 454 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset));
423 DCHECK_NE(kNoRVA, target_rva); 455 DCHECK_NE(kNoRVA, target_rva);
424 456
425 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva))) 457 Label* label = program->FindAbs32Label(target_rva);
458 CHECK(label);
459 if (!program->EmitAbs32(label))
426 return false; 460 return false;
427 file_offset += sizeof(RVA); 461 file_offset += sizeof(RVA);
428 ++(*current_abs_offset); 462 ++(*current_abs_offset);
429 continue; 463 continue;
430 } 464 }
431 465
432 if (*current_rel != end_rel && 466 if (*current_rel != end_rel &&
433 file_offset == (**current_rel)->file_offset()) { 467 file_offset == (**current_rel)->file_offset()) {
434 uint32_t relative_target = (**current_rel)->relative_target(); 468 uint32_t relative_target = (**current_rel)->relative_target();
469 CHECK_EQ(RVA(origin + (file_offset - origin_offset)),
470 (**current_rel)->rva());
435 // This cast is for 64 bit systems, and is only safe because we 471 // This cast is for 64 bit systems, and is only safe because we
436 // are working on 32 bit executables. 472 // are working on 32 bit executables.
437 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) + 473 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) +
438 relative_target); 474 relative_target);
439 475
440 if (!(**current_rel)->EmitInstruction(program, target_rva)) 476 Label* label = program->FindRel32Label(target_rva);
477 CHECK(label);
478
479 if (!(**current_rel)->EmitInstruction(program, label))
441 return false; 480 return false;
442 file_offset += (**current_rel)->op_size(); 481 file_offset += (**current_rel)->op_size();
443 ++(*current_rel); 482 ++(*current_rel);
444 continue; 483 continue;
445 } 484 }
446 } 485 }
447 486
448 // Rest of the section (if any) 487 // Rest of the section (if any)
449 return ParseSimpleRegion(file_offset, section_end, program); 488 return ParseSimpleRegion(file_offset, section_end, program);
450 } 489 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 if (!ParseRel32RelocsFromSection(section_header)) 587 if (!ParseRel32RelocsFromSection(section_header))
549 return false; 588 return false;
550 } 589 }
551 if (!found_rel32) 590 if (!found_rel32)
552 VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?"; 591 VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?";
553 592
554 return true; 593 return true;
555 } 594 }
556 595
557 } // namespace courgette 596 } // namespace courgette
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698