LEFT | RIGHT |
(no file at all) | |
1 // Copyright (c) 2010, Google Inc. | 1 // Copyright (c) 2010, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 // How many object files does this fat binary contain? | 94 // How many object files does this fat binary contain? |
95 uint32_t object_files_count; | 95 uint32_t object_files_count; |
96 if (!(cursor >> object_files_count)) { // nfat_arch | 96 if (!(cursor >> object_files_count)) { // nfat_arch |
97 reporter_->TooShort(); | 97 reporter_->TooShort(); |
98 return false; | 98 return false; |
99 } | 99 } |
100 | 100 |
101 // Read the list of object files. | 101 // Read the list of object files. |
102 object_files_.resize(object_files_count); | 102 object_files_.resize(object_files_count); |
103 for (size_t i = 0; i < object_files_count; i++) { | 103 for (size_t i = 0; i < object_files_count; i++) { |
104 struct fat_arch *objfile = &object_files_[i]; | 104 struct fat_arch objfile; |
105 | 105 |
106 // Read this object file entry, byte-swapping as appropriate. | 106 // Read this object file entry, byte-swapping as appropriate. |
107 cursor >> objfile->cputype | 107 cursor >> objfile.cputype |
108 >> objfile->cpusubtype | 108 >> objfile.cpusubtype |
109 >> objfile->offset | 109 >> objfile.offset |
110 >> objfile->size | 110 >> objfile.size |
111 >> objfile->align; | 111 >> objfile.align; |
| 112 |
| 113 SuperFatArch super_fat_arch(objfile); |
| 114 object_files_[i] = super_fat_arch; |
| 115 |
112 if (!cursor) { | 116 if (!cursor) { |
113 reporter_->TooShort(); | 117 reporter_->TooShort(); |
114 return false; | 118 return false; |
115 } | 119 } |
116 // Does the file actually have the bytes this entry refers to? | 120 // Does the file actually have the bytes this entry refers to? |
117 size_t fat_size = buffer_.Size(); | 121 size_t fat_size = buffer_.Size(); |
118 if (objfile->offset > fat_size || | 122 if (objfile.offset > fat_size || |
119 objfile->size > fat_size - objfile->offset) { | 123 objfile.size > fat_size - objfile.offset) { |
120 reporter_->MisplacedObjectFile(); | 124 reporter_->MisplacedObjectFile(); |
121 return false; | 125 return false; |
122 } | 126 } |
123 } | 127 } |
124 | 128 |
125 return true; | 129 return true; |
126 } else if (magic_ == MH_MAGIC || magic_ == MH_MAGIC_64 || | 130 } else if (magic_ == MH_MAGIC || magic_ == MH_MAGIC_64 || |
127 magic_ == MH_CIGAM || magic_ == MH_CIGAM_64) { | 131 magic_ == MH_CIGAM || magic_ == MH_CIGAM_64) { |
128 // If this is a little-endian Mach-O file, fix the cursor's endianness. | 132 // If this is a little-endian Mach-O file, fix the cursor's endianness. |
129 if (magic_ == MH_CIGAM || magic_ == MH_CIGAM_64) | 133 if (magic_ == MH_CIGAM || magic_ == MH_CIGAM_64) |
130 cursor.set_big_endian(false); | 134 cursor.set_big_endian(false); |
131 // Record the entire file as a single entry in the object file list. | 135 // Record the entire file as a single entry in the object file list. |
132 object_files_.resize(1); | 136 object_files_.resize(1); |
133 | 137 |
134 // Get the cpu type and subtype from the Mach-O header. | 138 // Get the cpu type and subtype from the Mach-O header. |
135 if (!(cursor >> object_files_[0].cputype | 139 if (!(cursor >> object_files_[0].cputype |
136 >> object_files_[0].cpusubtype)) { | 140 >> object_files_[0].cpusubtype)) { |
137 reporter_->TooShort(); | 141 reporter_->TooShort(); |
138 return false; | 142 return false; |
139 } | 143 } |
140 | 144 |
141 object_files_[0].offset = 0; | 145 object_files_[0].offset = 0; |
142 object_files_[0].size = static_cast<uint32_t>(buffer_.Size()); | 146 object_files_[0].size = static_cast<uint64_t>(buffer_.Size()); |
143 // This alignment is correct for 32 and 64-bit x86 and ppc. | 147 // This alignment is correct for 32 and 64-bit x86 and ppc. |
144 // See get_align in the lipo source for other architectures: | 148 // See get_align in the lipo source for other architectures: |
145 // http://www.opensource.apple.com/source/cctools/cctools-773/misc/lipo.c | 149 // http://www.opensource.apple.com/source/cctools/cctools-773/misc/lipo.c |
146 object_files_[0].align = 12; // 2^12 == 4096 | 150 object_files_[0].align = 12; // 2^12 == 4096 |
147 | |
148 return true; | 151 return true; |
149 } | 152 } |
150 } | 153 } |
151 | |
152 reporter_->BadHeader(); | 154 reporter_->BadHeader(); |
153 return false; | 155 return false; |
154 } | 156 } |
155 | 157 |
156 void Reader::Reporter::BadHeader() { | 158 void Reader::Reporter::BadHeader() { |
157 fprintf(stderr, "%s: file is not a Mach-O object file\n", filename_.c_str()); | 159 fprintf(stderr, "%s: file is not a Mach-O object file\n", filename_.c_str()); |
158 } | 160 } |
159 | 161 |
160 void Reader::Reporter::CPUTypeMismatch(cpu_type_t cpu_type, | 162 void Reader::Reporter::CPUTypeMismatch(cpu_type_t cpu_type, |
161 cpu_subtype_t cpu_subtype, | 163 cpu_subtype_t cpu_subtype, |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 bool Reader::WalkLoadCommands(Reader::LoadCommandHandler *handler) const { | 310 bool Reader::WalkLoadCommands(Reader::LoadCommandHandler *handler) const { |
309 ByteCursor list_cursor(&load_commands_, big_endian_); | 311 ByteCursor list_cursor(&load_commands_, big_endian_); |
310 | 312 |
311 for (size_t index = 0; index < load_command_count_; ++index) { | 313 for (size_t index = 0; index < load_command_count_; ++index) { |
312 // command refers to this load command alone, so that cursor will | 314 // command refers to this load command alone, so that cursor will |
313 // refuse to read past the load command's end. But since we haven't | 315 // refuse to read past the load command's end. But since we haven't |
314 // read the size yet, let command initially refer to the entire | 316 // read the size yet, let command initially refer to the entire |
315 // remainder of the load command series. | 317 // remainder of the load command series. |
316 ByteBuffer command(list_cursor.here(), list_cursor.Available()); | 318 ByteBuffer command(list_cursor.here(), list_cursor.Available()); |
317 ByteCursor cursor(&command, big_endian_); | 319 ByteCursor cursor(&command, big_endian_); |
318 | 320 |
319 // Read the command type and size --- fields common to all commands. | 321 // Read the command type and size --- fields common to all commands. |
320 uint32_t type, size; | 322 uint32_t type, size; |
321 if (!(cursor >> type)) { | 323 if (!(cursor >> type)) { |
322 reporter_->LoadCommandsOverrun(load_command_count_, index, 0); | 324 reporter_->LoadCommandsOverrun(load_command_count_, index, 0); |
323 return false; | 325 return false; |
324 } | 326 } |
325 if (!(cursor >> size) || size > command.Size()) { | 327 if (!(cursor >> size) || size > command.Size()) { |
326 reporter_->LoadCommandsOverrun(load_command_count_, index, type); | 328 reporter_->LoadCommandsOverrun(load_command_count_, index, type); |
327 return false; | 329 return false; |
328 } | 330 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 stroff > buffer_.Size() || strsize > buffer_.Size() - stroff) { | 395 stroff > buffer_.Size() || strsize > buffer_.Size() - stroff) { |
394 reporter_->MisplacedSymbolTable(); | 396 reporter_->MisplacedSymbolTable(); |
395 return false; | 397 return false; |
396 } | 398 } |
397 ByteBuffer entries(buffer_.start + symoff, symbols_size); | 399 ByteBuffer entries(buffer_.start + symoff, symbols_size); |
398 ByteBuffer names(buffer_.start + stroff, strsize); | 400 ByteBuffer names(buffer_.start + stroff, strsize); |
399 if (!handler->SymtabCommand(entries, names)) | 401 if (!handler->SymtabCommand(entries, names)) |
400 return false; | 402 return false; |
401 break; | 403 break; |
402 } | 404 } |
403 | 405 |
404 default: { | 406 default: { |
405 if (!handler->UnknownCommand(type, command)) | 407 if (!handler->UnknownCommand(type, command)) |
406 return false; | 408 return false; |
407 break; | 409 break; |
408 } | 410 } |
409 } | 411 } |
410 | 412 |
411 list_cursor.set_here(command.end); | 413 list_cursor.set_here(command.end); |
412 } | 414 } |
413 | 415 |
414 return true; | 416 return true; |
415 } | 417 } |
416 | 418 |
417 // A load command handler that looks for a segment of a given name. | 419 // A load command handler that looks for a segment of a given name. |
418 class Reader::SegmentFinder : public LoadCommandHandler { | 420 class Reader::SegmentFinder : public LoadCommandHandler { |
419 public: | 421 public: |
420 // Create a load command handler that looks for a segment named NAME, | 422 // Create a load command handler that looks for a segment named NAME, |
421 // and sets SEGMENT to describe it if found. | 423 // and sets SEGMENT to describe it if found. |
422 SegmentFinder(const string &name, Segment *segment) | 424 SegmentFinder(const string &name, Segment *segment) |
423 : name_(name), segment_(segment), found_() { } | 425 : name_(name), segment_(segment), found_() { } |
424 | 426 |
425 // Return true if the traversal found the segment, false otherwise. | 427 // Return true if the traversal found the segment, false otherwise. |
426 bool found() const { return found_; } | 428 bool found() const { return found_; } |
427 | 429 |
428 bool SegmentCommand(const Segment &segment) { | 430 bool SegmentCommand(const Segment &segment) { |
429 if (segment.name == name_) { | 431 if (segment.name == name_) { |
430 *segment_ = segment; | 432 *segment_ = segment; |
431 found_ = true; | 433 found_ = true; |
432 return false; | 434 return false; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 >> dummy32; | 477 >> dummy32; |
476 if (section.bits_64) | 478 if (section.bits_64) |
477 cursor >> dummy32; | 479 cursor >> dummy32; |
478 if (!cursor) { | 480 if (!cursor) { |
479 reporter_->SectionsMissing(segment.name); | 481 reporter_->SectionsMissing(segment.name); |
480 return false; | 482 return false; |
481 } | 483 } |
482 if ((section.flags & SECTION_TYPE) == S_ZEROFILL) { | 484 if ((section.flags & SECTION_TYPE) == S_ZEROFILL) { |
483 // Zero-fill sections have a size, but no contents. | 485 // Zero-fill sections have a size, but no contents. |
484 section.contents.start = section.contents.end = NULL; | 486 section.contents.start = section.contents.end = NULL; |
485 } else if (segment.contents.start == NULL && | 487 } else if (segment.contents.start == NULL && |
486 segment.contents.end == NULL) { | 488 segment.contents.end == NULL) { |
487 // Mach-O files in .dSYM bundles have the contents of the loaded | 489 // Mach-O files in .dSYM bundles have the contents of the loaded |
488 // segments removed, and their file offsets and file sizes zeroed | 490 // segments removed, and their file offsets and file sizes zeroed |
489 // out. However, the sections within those segments still have | 491 // out. However, the sections within those segments still have |
490 // non-zero sizes. There's no reason to call MisplacedSectionData in | 492 // non-zero sizes. There's no reason to call MisplacedSectionData in |
491 // this case; the caller may just need the section's load | 493 // this case; the caller may just need the section's load |
492 // address. But do set the contents' limits to NULL, for safety. | 494 // address. But do set the contents' limits to NULL, for safety. |
493 section.contents.start = section.contents.end = NULL; | 495 section.contents.start = section.contents.end = NULL; |
494 } else { | 496 } else { |
495 if (offset < size_t(segment.contents.start - buffer_.start) || | 497 if (offset < size_t(segment.contents.start - buffer_.start) || |
(...skipping 30 matching lines...) Expand all Loading... |
526 | 528 |
527 bool Reader::MapSegmentSections(const Segment &segment, | 529 bool Reader::MapSegmentSections(const Segment &segment, |
528 SectionMap *section_map) const { | 530 SectionMap *section_map) const { |
529 section_map->clear(); | 531 section_map->clear(); |
530 SectionMapper mapper(section_map); | 532 SectionMapper mapper(section_map); |
531 return WalkSegmentSections(segment, &mapper); | 533 return WalkSegmentSections(segment, &mapper); |
532 } | 534 } |
533 | 535 |
534 } // namespace mach_o | 536 } // namespace mach_o |
535 } // namespace google_breakpad | 537 } // namespace google_breakpad |
LEFT | RIGHT |