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

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: Sync. 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
« no previous file with comments | « courgette/disassembler_elf_32.h ('k') | courgette/disassembler_elf_32_arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include <iterator>
8 #include <utility> 9 #include <utility>
9 10
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "courgette/assembly_program.h" 12 #include "courgette/assembly_program.h"
12 #include "courgette/courgette.h" 13 #include "courgette/courgette.h"
13 14
14 namespace courgette { 15 namespace courgette {
15 16
16 namespace { 17 namespace {
17 18
18 // Sorts |section_headers| by file offset and stores the resulting permutation 19 // Sorts |section_headers| by file offset and stores the resulting permutation
19 // of section ids in |order|. 20 // of section ids in |order|.
20 std::vector<Elf32_Half> GetSectionHeaderFileOffsetOrder( 21 std::vector<Elf32_Half> GetSectionHeaderFileOffsetOrder(
21 const std::vector<Elf32_Shdr>& section_headers) { 22 const std::vector<Elf32_Shdr>& section_headers) {
22 size_t size = section_headers.size(); 23 size_t size = section_headers.size();
23 std::vector<Elf32_Half> order(size); 24 std::vector<Elf32_Half> order(size);
24 for (size_t i = 0; i < size; ++i) 25 for (size_t i = 0; i < size; ++i)
25 order[i] = static_cast<Elf32_Half>(i); 26 order[i] = static_cast<Elf32_Half>(i);
26 27
27 auto comp = [&](int idx1, int idx2) { 28 auto comp = [&](int idx1, int idx2) {
28 return section_headers[idx1].sh_offset < section_headers[idx2].sh_offset; 29 return section_headers[idx1].sh_offset < section_headers[idx2].sh_offset;
29 }; 30 };
30 std::stable_sort(order.begin(), order.end(), comp); 31 std::stable_sort(order.begin(), order.end(), comp);
31 return order; 32 return order;
32 } 33 }
33 34
34 } // namespace 35 } // namespace
35 36
37 DisassemblerElf32::Elf32RvaVisitor_Rel32::Elf32RvaVisitor_Rel32(
38 const std::vector<std::unique_ptr<TypedRVA>>& rva_locations)
39 : VectorRvaVisitor<std::unique_ptr<TypedRVA>>(rva_locations) {
40 }
41
42 RVA DisassemblerElf32::Elf32RvaVisitor_Rel32::Get() const {
43 return (*it_)->rva() + (*it_)->relative_target();
44 }
45
36 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length) 46 DisassemblerElf32::DisassemblerElf32(const void* start, size_t length)
37 : Disassembler(start, length), 47 : Disassembler(start, length),
38 header_(nullptr), 48 header_(nullptr),
39 section_header_table_size_(0), 49 section_header_table_size_(0),
40 program_header_table_(nullptr), 50 program_header_table_(nullptr),
41 program_header_table_size_(0), 51 program_header_table_size_(0),
42 default_string_section_(nullptr) { 52 default_string_section_(nullptr) {
43 } 53 }
44 54
45 RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const { 55 RVA DisassemblerElf32::FileOffsetToRVA(FileOffset offset) const {
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) { 167 bool DisassemblerElf32::Disassemble(AssemblyProgram* target) {
158 if (!ok()) 168 if (!ok())
159 return false; 169 return false;
160 170
161 // The Image Base is always 0 for ELF Executables 171 // The Image Base is always 0 for ELF Executables
162 target->set_image_base(0); 172 target->set_image_base(0);
163 173
164 if (!ParseAbs32Relocs()) 174 if (!ParseAbs32Relocs())
165 return false; 175 return false;
166 176
167 if (!ParseRel32RelocsFromSections()) 177 if (!ParseRel32RelocsFromSections()) // Does not sort rel32 locations.
168 return false; 178 return false;
169 179
180 PrecomputeLabels(target);
181 RemoveUnusedRel32Locations(target);
182
170 if (!ParseFile(target)) 183 if (!ParseFile(target))
171 return false; 184 return false;
172 185
186 // Finally sort rel32 locations.
173 std::sort(rel32_locations_.begin(), 187 std::sort(rel32_locations_.begin(),
174 rel32_locations_.end(), 188 rel32_locations_.end(),
175 TypedRVA::IsLessThanByRVA); 189 TypedRVA::IsLessThanByRVA);
176 DCHECK(rel32_locations_.empty() || 190 DCHECK(rel32_locations_.empty() ||
177 rel32_locations_.back()->rva() != kUnassignedRVA); 191 rel32_locations_.back()->rva() != kUnassignedRVA);
178 192
179 target->DefaultAssignIndexes(); 193 target->DefaultAssignIndexes();
180 return true; 194 return true;
181 } 195 }
182 196
197 CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const {
198 if (rva == kUnassignedRVA)
199 return false;
200
201 // |rva| is valid if it's contained in any program segment.
202 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
203 ++segment_id) {
204 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
205
206 if (segment_header->p_type != PT_LOAD)
207 continue;
208
209 Elf32_Addr begin = segment_header->p_vaddr;
210 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
211
212 if (rva >= begin && rva < end)
213 return true;
214 }
215
216 return false;
217 }
218
183 bool DisassemblerElf32::UpdateLength() { 219 bool DisassemblerElf32::UpdateLength() {
184 Elf32_Off result = 0; 220 Elf32_Off result = 0;
185 221
186 // Find the end of the last section 222 // Find the end of the last section
187 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount(); 223 for (Elf32_Half section_id = 0; section_id < SectionHeaderCount();
188 ++section_id) { 224 ++section_id) {
189 const Elf32_Shdr* section_header = SectionHeader(section_id); 225 const Elf32_Shdr* section_header = SectionHeader(section_id);
190 226
191 if (section_header->sh_type == SHT_NOBITS) 227 if (section_header->sh_type == SHT_NOBITS)
192 continue; 228 continue;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 name->clear(); 267 name->clear();
232 } else { 268 } else {
233 if (string_pos >= default_string_section_size_) 269 if (string_pos >= default_string_section_size_)
234 return false; 270 return false;
235 // Safe because string section must terminate with null. 271 // Safe because string section must terminate with null.
236 *name = default_string_section_ + string_pos; 272 *name = default_string_section_ + string_pos;
237 } 273 }
238 return true; 274 return true;
239 } 275 }
240 276
241 CheckBool DisassemblerElf32::IsValidTargetRVA(RVA rva) const {
242 if (rva == kUnassignedRVA)
243 return false;
244
245 // It's valid if it's contained in any program segment
246 for (Elf32_Half segment_id = 0; segment_id < ProgramSegmentHeaderCount();
247 ++segment_id) {
248 const Elf32_Phdr* segment_header = ProgramSegmentHeader(segment_id);
249
250 if (segment_header->p_type != PT_LOAD)
251 continue;
252
253 Elf32_Addr begin = segment_header->p_vaddr;
254 Elf32_Addr end = segment_header->p_vaddr + segment_header->p_memsz;
255
256 if (rva >= begin && rva < end)
257 return true;
258 }
259
260 return false;
261 }
262
263 CheckBool DisassemblerElf32::RVAsToFileOffsets( 277 CheckBool DisassemblerElf32::RVAsToFileOffsets(
264 const std::vector<RVA>& rvas, 278 const std::vector<RVA>& rvas,
265 std::vector<FileOffset>* file_offsets) { 279 std::vector<FileOffset>* file_offsets) {
266 file_offsets->clear(); 280 file_offsets->clear();
281 file_offsets->reserve(rvas.size());
267 for (RVA rva : rvas) { 282 for (RVA rva : rvas) {
268 FileOffset file_offset = RVAToFileOffset(rva); 283 FileOffset file_offset = RVAToFileOffset(rva);
269 if (file_offset == kNoFileOffset) 284 if (file_offset == kNoFileOffset)
270 return false; 285 return false;
271 file_offsets->push_back(file_offset); 286 file_offsets->push_back(file_offset);
272 } 287 }
273 return true; 288 return true;
274 } 289 }
275 290
276 CheckBool DisassemblerElf32::RVAsToFileOffsets( 291 CheckBool DisassemblerElf32::RVAsToFileOffsets(
277 std::vector<std::unique_ptr<TypedRVA>>* typed_rvas) { 292 std::vector<std::unique_ptr<TypedRVA>>* typed_rvas) {
278 for (auto& typed_rva : *typed_rvas) { 293 for (auto& typed_rva : *typed_rvas) {
279 FileOffset file_offset = RVAToFileOffset(typed_rva->rva()); 294 FileOffset file_offset = RVAToFileOffset(typed_rva->rva());
280 if (file_offset == kNoFileOffset) 295 if (file_offset == kNoFileOffset)
281 return false; 296 return false;
282 typed_rva->set_file_offset(file_offset); 297 typed_rva->set_file_offset(file_offset);
283 } 298 }
284 return true; 299 return true;
285 } 300 }
286 301
302 RvaVisitor* DisassemblerElf32::CreateAbs32TargetRvaVisitor() {
303 return new RvaVisitor_Abs32(abs32_locations_, *this);
304 }
305
306 RvaVisitor* DisassemblerElf32::CreateRel32TargetRvaVisitor() {
307 return new Elf32RvaVisitor_Rel32(rel32_locations_);
308 }
309
310 void DisassemblerElf32::RemoveUnusedRel32Locations(AssemblyProgram* program) {
311 auto tail_it = rel32_locations_.begin();
312 for (auto head_it = rel32_locations_.begin();
313 head_it != rel32_locations_.end(); ++head_it) {
314 RVA target_rva = (*head_it)->rva() + (*head_it)->relative_target();
315 if (program->FindRel32Label(target_rva) == nullptr) {
316 // If address does not match a Label (because it was removed), deallocate.
317 (*head_it).reset(nullptr);
318 } else {
319 // Else squeeze nullptr to end to compactify.
320 if (tail_it != head_it)
321 (*tail_it).swap(*head_it);
322 ++tail_it;
323 }
324 }
325 rel32_locations_.resize(std::distance(rel32_locations_.begin(), tail_it));
326 }
327
287 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) { 328 CheckBool DisassemblerElf32::ParseFile(AssemblyProgram* program) {
288 // Walk all the bytes in the file, whether or not in a section. 329 // Walk all the bytes in the file, whether or not in a section.
289 FileOffset file_offset = 0; 330 FileOffset file_offset = 0;
290 331
291 std::vector<FileOffset> abs_offsets; 332 std::vector<FileOffset> abs_offsets;
292 333
293 // File parsing follows file offset order, and we visit abs32 and rel32 334 // File parsing follows file offset order, and we visit abs32 and rel32
294 // locations in lockstep. Therefore we need to extract and sort file offsets 335 // locations in lockstep. Therefore we need to extract and sort file offsets
295 // of all abs32 and rel32 locations. 336 // of all abs32 and rel32 locations.
296 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets)) 337 if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets))
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 459
419 file_offset = next_relocation; 460 file_offset = next_relocation;
420 continue; 461 continue;
421 } 462 }
422 463
423 if (*current_abs_offset != end_abs_offset && 464 if (*current_abs_offset != end_abs_offset &&
424 file_offset == **current_abs_offset) { 465 file_offset == **current_abs_offset) {
425 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset)); 466 RVA target_rva = PointerToTargetRVA(FileOffsetToPointer(file_offset));
426 DCHECK_NE(kNoRVA, target_rva); 467 DCHECK_NE(kNoRVA, target_rva);
427 468
428 if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva))) 469 Label* label = program->FindAbs32Label(target_rva);
470 CHECK(label);
471 if (!program->EmitAbs32(label))
429 return false; 472 return false;
430 file_offset += sizeof(RVA); 473 file_offset += sizeof(RVA);
431 ++(*current_abs_offset); 474 ++(*current_abs_offset);
432 continue; 475 continue;
433 } 476 }
434 477
435 if (*current_rel != end_rel && 478 if (*current_rel != end_rel &&
436 file_offset == (**current_rel)->file_offset()) { 479 file_offset == (**current_rel)->file_offset()) {
437 uint32_t relative_target = (**current_rel)->relative_target(); 480 uint32_t relative_target = (**current_rel)->relative_target();
481 CHECK_EQ(RVA(origin + (file_offset - origin_offset)),
482 (**current_rel)->rva());
438 // This cast is for 64 bit systems, and is only safe because we 483 // This cast is for 64 bit systems, and is only safe because we
439 // are working on 32 bit executables. 484 // are working on 32 bit executables.
440 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) + 485 RVA target_rva = (RVA)(origin + (file_offset - origin_offset) +
441 relative_target); 486 relative_target);
442 487
443 if (!(**current_rel)->EmitInstruction(program, target_rva)) 488 Label* label = program->FindRel32Label(target_rva);
489 CHECK(label);
490
491 if (!(**current_rel)->EmitInstruction(program, label))
444 return false; 492 return false;
445 file_offset += (**current_rel)->op_size(); 493 file_offset += (**current_rel)->op_size();
446 ++(*current_rel); 494 ++(*current_rel);
447 continue; 495 continue;
448 } 496 }
449 } 497 }
450 498
451 // Rest of the section (if any) 499 // Rest of the section (if any)
452 return ParseSimpleRegion(file_offset, section_end, program); 500 return ParseSimpleRegion(file_offset, section_end, program);
453 } 501 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 if (!ParseRel32RelocsFromSection(section_header)) 599 if (!ParseRel32RelocsFromSection(section_header))
552 return false; 600 return false;
553 } 601 }
554 if (!found_rel32) 602 if (!found_rel32)
555 VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?"; 603 VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?";
556 604
557 return true; 605 return true;
558 } 606 }
559 607
560 } // namespace courgette 608 } // namespace courgette
OLDNEW
« no previous file with comments | « courgette/disassembler_elf_32.h ('k') | courgette/disassembler_elf_32_arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698