1*9712c20fSFrederick Mayle // -*- mode: C++ -*- 2*9712c20fSFrederick Mayle 3*9712c20fSFrederick Mayle // Copyright 2010 Google LLC 4*9712c20fSFrederick Mayle // 5*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without 6*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are 7*9712c20fSFrederick Mayle // met: 8*9712c20fSFrederick Mayle // 9*9712c20fSFrederick Mayle // * Redistributions of source code must retain the above copyright 10*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer. 11*9712c20fSFrederick Mayle // * Redistributions in binary form must reproduce the above 12*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer 13*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the 14*9712c20fSFrederick Mayle // distribution. 15*9712c20fSFrederick Mayle // * Neither the name of Google LLC nor the names of its 16*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from 17*9712c20fSFrederick Mayle // this software without specific prior written permission. 18*9712c20fSFrederick Mayle // 19*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*9712c20fSFrederick Mayle 31*9712c20fSFrederick Mayle // Original author: Jim Blandy <[email protected]> <[email protected]> 32*9712c20fSFrederick Mayle 33*9712c20fSFrederick Mayle // macho_reader.h: A class for parsing Mach-O files. 34*9712c20fSFrederick Mayle 35*9712c20fSFrederick Mayle #ifndef BREAKPAD_COMMON_MAC_MACHO_READER_H_ 36*9712c20fSFrederick Mayle #define BREAKPAD_COMMON_MAC_MACHO_READER_H_ 37*9712c20fSFrederick Mayle 38*9712c20fSFrederick Mayle #include <mach-o/loader.h> 39*9712c20fSFrederick Mayle #include <mach-o/fat.h> 40*9712c20fSFrederick Mayle #include <stdint.h> 41*9712c20fSFrederick Mayle #include <stdlib.h> 42*9712c20fSFrederick Mayle #include <unistd.h> 43*9712c20fSFrederick Mayle 44*9712c20fSFrederick Mayle #include <map> 45*9712c20fSFrederick Mayle #include <string> 46*9712c20fSFrederick Mayle #include <vector> 47*9712c20fSFrederick Mayle 48*9712c20fSFrederick Mayle #include "common/byte_cursor.h" 49*9712c20fSFrederick Mayle #include "common/mac/super_fat_arch.h" 50*9712c20fSFrederick Mayle 51*9712c20fSFrederick Mayle namespace google_breakpad { 52*9712c20fSFrederick Mayle namespace mach_o { 53*9712c20fSFrederick Mayle 54*9712c20fSFrederick Mayle using std::map; 55*9712c20fSFrederick Mayle using std::string; 56*9712c20fSFrederick Mayle using std::vector; 57*9712c20fSFrederick Mayle 58*9712c20fSFrederick Mayle // The Mac headers don't specify particular types for these groups of 59*9712c20fSFrederick Mayle // constants, but defining them here provides some documentation 60*9712c20fSFrederick Mayle // value. We also give them the same width as the fields in which 61*9712c20fSFrederick Mayle // they appear, which makes them a bit easier to use with ByteCursors. 62*9712c20fSFrederick Mayle typedef uint32_t Magic; 63*9712c20fSFrederick Mayle typedef uint32_t FileType; 64*9712c20fSFrederick Mayle typedef uint32_t FileFlags; 65*9712c20fSFrederick Mayle typedef uint32_t LoadCommandType; 66*9712c20fSFrederick Mayle typedef uint32_t SegmentFlags; 67*9712c20fSFrederick Mayle typedef uint32_t SectionFlags; 68*9712c20fSFrederick Mayle 69*9712c20fSFrederick Mayle // A parser for fat binary files, used to store universal binaries. 70*9712c20fSFrederick Mayle // When applied to a (non-fat) Mach-O file, this behaves as if the 71*9712c20fSFrederick Mayle // file were a fat file containing a single object file. 72*9712c20fSFrederick Mayle class FatReader { 73*9712c20fSFrederick Mayle public: 74*9712c20fSFrederick Mayle 75*9712c20fSFrederick Mayle // A class for reporting errors found while parsing fat binary files. The 76*9712c20fSFrederick Mayle // default definitions of these methods print messages to stderr. 77*9712c20fSFrederick Mayle class Reporter { 78*9712c20fSFrederick Mayle public: 79*9712c20fSFrederick Mayle // Create a reporter that attributes problems to |filename|. Reporter(const string & filename)80*9712c20fSFrederick Mayle explicit Reporter(const string& filename) : filename_(filename) { } 81*9712c20fSFrederick Mayle ~Reporter()82*9712c20fSFrederick Mayle virtual ~Reporter() { } 83*9712c20fSFrederick Mayle 84*9712c20fSFrederick Mayle // The data does not begin with a fat binary or Mach-O magic number. 85*9712c20fSFrederick Mayle // This is a fatal error. 86*9712c20fSFrederick Mayle virtual void BadHeader(); 87*9712c20fSFrederick Mayle 88*9712c20fSFrederick Mayle // The Mach-O fat binary file ends abruptly, without enough space 89*9712c20fSFrederick Mayle // to contain an object file it claims is present. 90*9712c20fSFrederick Mayle virtual void MisplacedObjectFile(); 91*9712c20fSFrederick Mayle 92*9712c20fSFrederick Mayle // The file ends abruptly: either it is not large enough to hold a 93*9712c20fSFrederick Mayle // complete header, or the header implies that contents are present 94*9712c20fSFrederick Mayle // beyond the actual end of the file. 95*9712c20fSFrederick Mayle virtual void TooShort(); 96*9712c20fSFrederick Mayle 97*9712c20fSFrederick Mayle private: 98*9712c20fSFrederick Mayle // The filename to which the reader should attribute problems. 99*9712c20fSFrederick Mayle string filename_; 100*9712c20fSFrederick Mayle }; 101*9712c20fSFrederick Mayle 102*9712c20fSFrederick Mayle // Create a fat binary file reader that uses |reporter| to report problems. FatReader(Reporter * reporter)103*9712c20fSFrederick Mayle explicit FatReader(Reporter* reporter) : reporter_(reporter) { } 104*9712c20fSFrederick Mayle 105*9712c20fSFrederick Mayle // Read the |size| bytes at |buffer| as a fat binary file. On success, 106*9712c20fSFrederick Mayle // return true; on failure, report the problem to reporter_ and return 107*9712c20fSFrederick Mayle // false. 108*9712c20fSFrederick Mayle // 109*9712c20fSFrederick Mayle // If the data is a plain Mach-O file, rather than a fat binary file, 110*9712c20fSFrederick Mayle // then the reader behaves as if it had found a fat binary file whose 111*9712c20fSFrederick Mayle // single object file is the Mach-O file. 112*9712c20fSFrederick Mayle bool Read(const uint8_t* buffer, size_t size); 113*9712c20fSFrederick Mayle 114*9712c20fSFrederick Mayle // Return an array of 'SuperFatArch' structures describing the 115*9712c20fSFrederick Mayle // object files present in this fat binary file. Set |size| to the 116*9712c20fSFrederick Mayle // number of elements in the array. 117*9712c20fSFrederick Mayle // 118*9712c20fSFrederick Mayle // Assuming Read returned true, the entries are validated: it is safe to 119*9712c20fSFrederick Mayle // assume that the offsets and sizes in each SuperFatArch refer to subranges 120*9712c20fSFrederick Mayle // of the bytes passed to Read. 121*9712c20fSFrederick Mayle // 122*9712c20fSFrederick Mayle // If there are no object files in this fat binary, then this 123*9712c20fSFrederick Mayle // function can return NULL. 124*9712c20fSFrederick Mayle // 125*9712c20fSFrederick Mayle // The array is owned by this FatReader instance; it will be freed when 126*9712c20fSFrederick Mayle // this FatReader is destroyed. 127*9712c20fSFrederick Mayle // 128*9712c20fSFrederick Mayle // This function returns a C-style array instead of a vector to make it 129*9712c20fSFrederick Mayle // possible to use the result with OS X functions like NXFindBestFatArch, 130*9712c20fSFrederick Mayle // so that the symbol dumper will behave consistently with other OS X 131*9712c20fSFrederick Mayle // utilities that work with fat binaries. object_files(size_t * count)132*9712c20fSFrederick Mayle const SuperFatArch* object_files(size_t* count) const { 133*9712c20fSFrederick Mayle *count = object_files_.size(); 134*9712c20fSFrederick Mayle if (object_files_.size() > 0) 135*9712c20fSFrederick Mayle return &object_files_[0]; 136*9712c20fSFrederick Mayle return NULL; 137*9712c20fSFrederick Mayle } 138*9712c20fSFrederick Mayle 139*9712c20fSFrederick Mayle private: 140*9712c20fSFrederick Mayle // We use this to report problems parsing the file's contents. (WEAK) 141*9712c20fSFrederick Mayle Reporter* reporter_; 142*9712c20fSFrederick Mayle 143*9712c20fSFrederick Mayle // The contents of the fat binary or Mach-O file we're parsing. We do not 144*9712c20fSFrederick Mayle // own the storage it refers to. 145*9712c20fSFrederick Mayle ByteBuffer buffer_; 146*9712c20fSFrederick Mayle 147*9712c20fSFrederick Mayle // The magic number of this binary, in host byte order. 148*9712c20fSFrederick Mayle Magic magic_; 149*9712c20fSFrederick Mayle 150*9712c20fSFrederick Mayle // The list of object files in this binary. 151*9712c20fSFrederick Mayle // object_files_.size() == fat_header.nfat_arch 152*9712c20fSFrederick Mayle vector<SuperFatArch> object_files_; 153*9712c20fSFrederick Mayle }; 154*9712c20fSFrederick Mayle 155*9712c20fSFrederick Mayle // A segment in a Mach-O file. All these fields have been byte-swapped as 156*9712c20fSFrederick Mayle // appropriate for use by the executing architecture. 157*9712c20fSFrederick Mayle struct Segment { 158*9712c20fSFrederick Mayle // The ByteBuffers below point into the bytes passed to the Reader that 159*9712c20fSFrederick Mayle // created this Segment. 160*9712c20fSFrederick Mayle 161*9712c20fSFrederick Mayle ByteBuffer section_list; // This segment's section list. 162*9712c20fSFrederick Mayle ByteBuffer contents; // This segment's contents. 163*9712c20fSFrederick Mayle 164*9712c20fSFrederick Mayle // This segment's name. 165*9712c20fSFrederick Mayle string name; 166*9712c20fSFrederick Mayle 167*9712c20fSFrederick Mayle // The address at which this segment should be loaded in memory. If 168*9712c20fSFrederick Mayle // bits_64 is false, only the bottom 32 bits of this value are valid. 169*9712c20fSFrederick Mayle uint64_t vmaddr; 170*9712c20fSFrederick Mayle 171*9712c20fSFrederick Mayle // The size of this segment when loaded into memory. This may be larger 172*9712c20fSFrederick Mayle // than contents.Size(), in which case the extra area will be 173*9712c20fSFrederick Mayle // initialized with zeros. If bits_64 is false, only the bottom 32 bits 174*9712c20fSFrederick Mayle // of this value are valid. 175*9712c20fSFrederick Mayle uint64_t vmsize; 176*9712c20fSFrederick Mayle 177*9712c20fSFrederick Mayle // The file offset and size of the segment in the Mach-O image. 178*9712c20fSFrederick Mayle uint64_t fileoff; 179*9712c20fSFrederick Mayle uint64_t filesize; 180*9712c20fSFrederick Mayle 181*9712c20fSFrederick Mayle // The maximum and initial VM protection of this segment's contents. 182*9712c20fSFrederick Mayle uint32_t maxprot; 183*9712c20fSFrederick Mayle uint32_t initprot; 184*9712c20fSFrederick Mayle 185*9712c20fSFrederick Mayle // The number of sections in section_list. 186*9712c20fSFrederick Mayle uint32_t nsects; 187*9712c20fSFrederick Mayle 188*9712c20fSFrederick Mayle // Flags describing this segment, from SegmentFlags. 189*9712c20fSFrederick Mayle uint32_t flags; 190*9712c20fSFrederick Mayle 191*9712c20fSFrederick Mayle // True if this is a 64-bit section; false if it is a 32-bit section. 192*9712c20fSFrederick Mayle bool bits_64; 193*9712c20fSFrederick Mayle }; 194*9712c20fSFrederick Mayle 195*9712c20fSFrederick Mayle // A section in a Mach-O file. All these fields have been byte-swapped as 196*9712c20fSFrederick Mayle // appropriate for use by the executing architecture. 197*9712c20fSFrederick Mayle struct Section { 198*9712c20fSFrederick Mayle // This section's contents. This points into the bytes passed to the 199*9712c20fSFrederick Mayle // Reader that created this Section. 200*9712c20fSFrederick Mayle ByteBuffer contents; 201*9712c20fSFrederick Mayle 202*9712c20fSFrederick Mayle // This section's name. 203*9712c20fSFrederick Mayle string section_name; // section[_64].sectname 204*9712c20fSFrederick Mayle // The name of the segment this section belongs to. 205*9712c20fSFrederick Mayle string segment_name; // section[_64].segname 206*9712c20fSFrederick Mayle 207*9712c20fSFrederick Mayle // The address at which this section's contents should be loaded in 208*9712c20fSFrederick Mayle // memory. If bits_64 is false, only the bottom 32 bits of this value 209*9712c20fSFrederick Mayle // are valid. 210*9712c20fSFrederick Mayle uint64_t address; 211*9712c20fSFrederick Mayle 212*9712c20fSFrederick Mayle // The contents of this section should be loaded into memory at an 213*9712c20fSFrederick Mayle // address which is a multiple of (two raised to this power). 214*9712c20fSFrederick Mayle uint32_t align; 215*9712c20fSFrederick Mayle 216*9712c20fSFrederick Mayle // Flags from SectionFlags describing the section's contents. 217*9712c20fSFrederick Mayle uint32_t flags; 218*9712c20fSFrederick Mayle 219*9712c20fSFrederick Mayle // We don't support reading relocations yet. 220*9712c20fSFrederick Mayle 221*9712c20fSFrederick Mayle // True if this is a 64-bit section; false if it is a 32-bit section. 222*9712c20fSFrederick Mayle bool bits_64; 223*9712c20fSFrederick Mayle }; 224*9712c20fSFrederick Mayle 225*9712c20fSFrederick Mayle // A map from section names to Sections. 226*9712c20fSFrederick Mayle typedef map<string, Section> SectionMap; 227*9712c20fSFrederick Mayle 228*9712c20fSFrederick Mayle // A reader for a Mach-O file. 229*9712c20fSFrederick Mayle // 230*9712c20fSFrederick Mayle // This does not handle fat binaries; see FatReader above. FatReader 231*9712c20fSFrederick Mayle // provides a friendly interface for parsing data that could be either a 232*9712c20fSFrederick Mayle // fat binary or a Mach-O file. 233*9712c20fSFrederick Mayle class Reader { 234*9712c20fSFrederick Mayle public: 235*9712c20fSFrederick Mayle 236*9712c20fSFrederick Mayle // A class for reporting errors found while parsing Mach-O files. The 237*9712c20fSFrederick Mayle // default definitions of these member functions print messages to 238*9712c20fSFrederick Mayle // stderr. 239*9712c20fSFrederick Mayle class Reporter { 240*9712c20fSFrederick Mayle public: 241*9712c20fSFrederick Mayle // Create a reporter that attributes problems to |filename|. Reporter(const string & filename)242*9712c20fSFrederick Mayle explicit Reporter(const string& filename) : filename_(filename) { } ~Reporter()243*9712c20fSFrederick Mayle virtual ~Reporter() { } 244*9712c20fSFrederick Mayle 245*9712c20fSFrederick Mayle // Reporter functions for fatal errors return void; the reader will 246*9712c20fSFrederick Mayle // definitely return an error to its caller after calling them 247*9712c20fSFrederick Mayle 248*9712c20fSFrederick Mayle // The data does not begin with a Mach-O magic number, or the magic 249*9712c20fSFrederick Mayle // number does not match the expected value for the cpu architecture. 250*9712c20fSFrederick Mayle // This is a fatal error. 251*9712c20fSFrederick Mayle virtual void BadHeader(); 252*9712c20fSFrederick Mayle 253*9712c20fSFrederick Mayle // The data contained in a Mach-O fat binary (|cpu_type|, |cpu_subtype|) 254*9712c20fSFrederick Mayle // does not match the expected CPU architecture 255*9712c20fSFrederick Mayle // (|expected_cpu_type|, |expected_cpu_subtype|). 256*9712c20fSFrederick Mayle virtual void CPUTypeMismatch(cpu_type_t cpu_type, 257*9712c20fSFrederick Mayle cpu_subtype_t cpu_subtype, 258*9712c20fSFrederick Mayle cpu_type_t expected_cpu_type, 259*9712c20fSFrederick Mayle cpu_subtype_t expected_cpu_subtype); 260*9712c20fSFrederick Mayle 261*9712c20fSFrederick Mayle // The file ends abruptly: either it is not large enough to hold a 262*9712c20fSFrederick Mayle // complete header, or the header implies that contents are present 263*9712c20fSFrederick Mayle // beyond the actual end of the file. 264*9712c20fSFrederick Mayle virtual void HeaderTruncated(); 265*9712c20fSFrederick Mayle 266*9712c20fSFrederick Mayle // The file's load command region, as given in the Mach-O header, is 267*9712c20fSFrederick Mayle // too large for the file. 268*9712c20fSFrederick Mayle virtual void LoadCommandRegionTruncated(); 269*9712c20fSFrederick Mayle 270*9712c20fSFrederick Mayle // The file's Mach-O header claims the file contains |claimed| load 271*9712c20fSFrederick Mayle // commands, but the I'th load command, of type |type|, extends beyond 272*9712c20fSFrederick Mayle // the end of the load command region, as given by the Mach-O header. 273*9712c20fSFrederick Mayle // If |type| is zero, the command's type was unreadable. 274*9712c20fSFrederick Mayle virtual void LoadCommandsOverrun(size_t claimed, size_t i, 275*9712c20fSFrederick Mayle LoadCommandType type); 276*9712c20fSFrederick Mayle 277*9712c20fSFrederick Mayle // The contents of the |i|'th load command, of type |type|, extend beyond 278*9712c20fSFrederick Mayle // the size given in the load command's header. 279*9712c20fSFrederick Mayle virtual void LoadCommandTooShort(size_t i, LoadCommandType type); 280*9712c20fSFrederick Mayle 281*9712c20fSFrederick Mayle // The LC_SEGMENT or LC_SEGMENT_64 load command for the segment named 282*9712c20fSFrederick Mayle // |name| is too short to hold the sections that its header says it does. 283*9712c20fSFrederick Mayle // (This more specific than LoadCommandTooShort.) 284*9712c20fSFrederick Mayle virtual void SectionsMissing(const string& name); 285*9712c20fSFrederick Mayle 286*9712c20fSFrederick Mayle // The segment named |name| claims that its contents lie beyond the end 287*9712c20fSFrederick Mayle // of the file. 288*9712c20fSFrederick Mayle virtual void MisplacedSegmentData(const string& name); 289*9712c20fSFrederick Mayle 290*9712c20fSFrederick Mayle // The section named |section| in the segment named |segment| claims that 291*9712c20fSFrederick Mayle // its contents do not lie entirely within the segment. 292*9712c20fSFrederick Mayle virtual void MisplacedSectionData(const string& section, 293*9712c20fSFrederick Mayle const string& segment); 294*9712c20fSFrederick Mayle 295*9712c20fSFrederick Mayle // The LC_SYMTAB command claims that symbol table contents are located 296*9712c20fSFrederick Mayle // beyond the end of the file. 297*9712c20fSFrederick Mayle virtual void MisplacedSymbolTable(); 298*9712c20fSFrederick Mayle 299*9712c20fSFrederick Mayle // An attempt was made to read a Mach-O file of the unsupported 300*9712c20fSFrederick Mayle // CPU architecture |cpu_type|. 301*9712c20fSFrederick Mayle virtual void UnsupportedCPUType(cpu_type_t cpu_type); 302*9712c20fSFrederick Mayle 303*9712c20fSFrederick Mayle private: 304*9712c20fSFrederick Mayle string filename_; 305*9712c20fSFrederick Mayle }; 306*9712c20fSFrederick Mayle 307*9712c20fSFrederick Mayle // A handler for sections parsed from a segment. The WalkSegmentSections 308*9712c20fSFrederick Mayle // member function accepts an instance of this class, and applies it to 309*9712c20fSFrederick Mayle // each section defined in a given segment. 310*9712c20fSFrederick Mayle class SectionHandler { 311*9712c20fSFrederick Mayle public: ~SectionHandler()312*9712c20fSFrederick Mayle virtual ~SectionHandler() { } 313*9712c20fSFrederick Mayle 314*9712c20fSFrederick Mayle // Called to report that the segment's section list contains |section|. 315*9712c20fSFrederick Mayle // This should return true if the iteration should continue, or false 316*9712c20fSFrederick Mayle // if it should stop. 317*9712c20fSFrederick Mayle virtual bool HandleSection(const Section& section) = 0; 318*9712c20fSFrederick Mayle }; 319*9712c20fSFrederick Mayle 320*9712c20fSFrederick Mayle // A handler for the load commands in a Mach-O file. 321*9712c20fSFrederick Mayle class LoadCommandHandler { 322*9712c20fSFrederick Mayle public: LoadCommandHandler()323*9712c20fSFrederick Mayle LoadCommandHandler() { } ~LoadCommandHandler()324*9712c20fSFrederick Mayle virtual ~LoadCommandHandler() { } 325*9712c20fSFrederick Mayle 326*9712c20fSFrederick Mayle // When called from WalkLoadCommands, the following handler functions 327*9712c20fSFrederick Mayle // should return true if they wish to continue iterating over the load 328*9712c20fSFrederick Mayle // command list, or false if they wish to stop iterating. 329*9712c20fSFrederick Mayle // 330*9712c20fSFrederick Mayle // When called from LoadCommandIterator::Handle or Reader::Handle, 331*9712c20fSFrederick Mayle // these functions' return values are simply passed through to Handle's 332*9712c20fSFrederick Mayle // caller. 333*9712c20fSFrederick Mayle // 334*9712c20fSFrederick Mayle // The definitions provided by this base class simply return true; the 335*9712c20fSFrederick Mayle // default is to silently ignore sections whose member functions the 336*9712c20fSFrederick Mayle // subclass doesn't override. 337*9712c20fSFrederick Mayle 338*9712c20fSFrederick Mayle // COMMAND is load command we don't recognize. We provide only the 339*9712c20fSFrederick Mayle // command type and a ByteBuffer enclosing the command's data (If we 340*9712c20fSFrederick Mayle // cannot parse the command type or its size, we call 341*9712c20fSFrederick Mayle // reporter_->IncompleteLoadCommand instead.) UnknownCommand(LoadCommandType type,const ByteBuffer & contents)342*9712c20fSFrederick Mayle virtual bool UnknownCommand(LoadCommandType type, 343*9712c20fSFrederick Mayle const ByteBuffer& contents) { 344*9712c20fSFrederick Mayle return true; 345*9712c20fSFrederick Mayle } 346*9712c20fSFrederick Mayle 347*9712c20fSFrederick Mayle // The load command is LC_SEGMENT or LC_SEGMENT_64, defining a segment 348*9712c20fSFrederick Mayle // with the properties given in |segment|. SegmentCommand(const Segment & segment)349*9712c20fSFrederick Mayle virtual bool SegmentCommand(const Segment& segment) { 350*9712c20fSFrederick Mayle return true; 351*9712c20fSFrederick Mayle } 352*9712c20fSFrederick Mayle 353*9712c20fSFrederick Mayle // The load command is LC_SYMTAB. |entries| holds the array of nlist 354*9712c20fSFrederick Mayle // entries, and |names| holds the strings the entries refer to. SymtabCommand(const ByteBuffer & entries,const ByteBuffer & names)355*9712c20fSFrederick Mayle virtual bool SymtabCommand(const ByteBuffer& entries, 356*9712c20fSFrederick Mayle const ByteBuffer& names) { 357*9712c20fSFrederick Mayle return true; 358*9712c20fSFrederick Mayle } 359*9712c20fSFrederick Mayle 360*9712c20fSFrederick Mayle // Add handler functions for more load commands here as needed. 361*9712c20fSFrederick Mayle }; 362*9712c20fSFrederick Mayle 363*9712c20fSFrederick Mayle // Create a Mach-O file reader that reports problems to |reporter|. Reader(Reporter * reporter)364*9712c20fSFrederick Mayle explicit Reader(Reporter* reporter) 365*9712c20fSFrederick Mayle : reporter_(reporter) { } 366*9712c20fSFrederick Mayle 367*9712c20fSFrederick Mayle // Read the given data as a Mach-O file. The reader retains pointers 368*9712c20fSFrederick Mayle // into the data passed, so the data should live as long as the reader 369*9712c20fSFrederick Mayle // does. On success, return true; on failure, return false. 370*9712c20fSFrederick Mayle // 371*9712c20fSFrederick Mayle // At most one of these functions should be invoked once on each Reader 372*9712c20fSFrederick Mayle // instance. 373*9712c20fSFrederick Mayle bool Read(const uint8_t* buffer, 374*9712c20fSFrederick Mayle size_t size, 375*9712c20fSFrederick Mayle cpu_type_t expected_cpu_type, 376*9712c20fSFrederick Mayle cpu_subtype_t expected_cpu_subtype); Read(const ByteBuffer & buffer,cpu_type_t expected_cpu_type,cpu_subtype_t expected_cpu_subtype)377*9712c20fSFrederick Mayle bool Read(const ByteBuffer& buffer, 378*9712c20fSFrederick Mayle cpu_type_t expected_cpu_type, 379*9712c20fSFrederick Mayle cpu_subtype_t expected_cpu_subtype) { 380*9712c20fSFrederick Mayle return Read(buffer.start, 381*9712c20fSFrederick Mayle buffer.Size(), 382*9712c20fSFrederick Mayle expected_cpu_type, 383*9712c20fSFrederick Mayle expected_cpu_subtype); 384*9712c20fSFrederick Mayle } 385*9712c20fSFrederick Mayle 386*9712c20fSFrederick Mayle // Return this file's characteristics, as found in the Mach-O header. cpu_type()387*9712c20fSFrederick Mayle cpu_type_t cpu_type() const { return cpu_type_; } cpu_subtype()388*9712c20fSFrederick Mayle cpu_subtype_t cpu_subtype() const { return cpu_subtype_; } file_type()389*9712c20fSFrederick Mayle FileType file_type() const { return file_type_; } flags()390*9712c20fSFrederick Mayle FileFlags flags() const { return flags_; } 391*9712c20fSFrederick Mayle 392*9712c20fSFrederick Mayle // Return true if this is a 64-bit Mach-O file, false if it is a 32-bit 393*9712c20fSFrederick Mayle // Mach-O file. bits_64()394*9712c20fSFrederick Mayle bool bits_64() const { return bits_64_; } 395*9712c20fSFrederick Mayle 396*9712c20fSFrederick Mayle // Return true if this is a big-endian Mach-O file, false if it is 397*9712c20fSFrederick Mayle // little-endian. big_endian()398*9712c20fSFrederick Mayle bool big_endian() const { return big_endian_; } 399*9712c20fSFrederick Mayle 400*9712c20fSFrederick Mayle // Apply |handler| to each load command in this Mach-O file, stopping when 401*9712c20fSFrederick Mayle // a handler function returns false. If we encounter a malformed load 402*9712c20fSFrederick Mayle // command, report it via reporter_ and return false. Return true if all 403*9712c20fSFrederick Mayle // load commands were parseable and all handlers returned true. 404*9712c20fSFrederick Mayle bool WalkLoadCommands(LoadCommandHandler* handler) const; 405*9712c20fSFrederick Mayle 406*9712c20fSFrederick Mayle // Set |segment| to describe the segment named |name|, if present. If 407*9712c20fSFrederick Mayle // found, |segment|'s byte buffers refer to a subregion of the bytes 408*9712c20fSFrederick Mayle // passed to Read. If we find the section, return true; otherwise, 409*9712c20fSFrederick Mayle // return false. 410*9712c20fSFrederick Mayle bool FindSegment(const string& name, Segment* segment) const; 411*9712c20fSFrederick Mayle 412*9712c20fSFrederick Mayle // Apply |handler| to each section defined in |segment|. If |handler| returns 413*9712c20fSFrederick Mayle // false, stop iterating and return false. If all calls to |handler| return 414*9712c20fSFrederick Mayle // true and we reach the end of the section list, return true. 415*9712c20fSFrederick Mayle bool WalkSegmentSections(const Segment& segment, SectionHandler* handler) 416*9712c20fSFrederick Mayle const; 417*9712c20fSFrederick Mayle 418*9712c20fSFrederick Mayle // Clear |section_map| and then populate it with a map of the sections 419*9712c20fSFrederick Mayle // in |segment|, from section names to Section structures. 420*9712c20fSFrederick Mayle // Each Section's contents refer to bytes in |segment|'s contents. 421*9712c20fSFrederick Mayle // On success, return true; if a problem occurs, report it and return false. 422*9712c20fSFrederick Mayle bool MapSegmentSections(const Segment& segment, SectionMap* section_map) 423*9712c20fSFrederick Mayle const; 424*9712c20fSFrederick Mayle 425*9712c20fSFrederick Mayle private: 426*9712c20fSFrederick Mayle // Used internally. 427*9712c20fSFrederick Mayle class SegmentFinder; 428*9712c20fSFrederick Mayle class SectionMapper; 429*9712c20fSFrederick Mayle 430*9712c20fSFrederick Mayle // We use this to report problems parsing the file's contents. (WEAK) 431*9712c20fSFrederick Mayle Reporter* reporter_; 432*9712c20fSFrederick Mayle 433*9712c20fSFrederick Mayle // The contents of the Mach-O file we're parsing. We do not own the 434*9712c20fSFrederick Mayle // storage it refers to. 435*9712c20fSFrederick Mayle ByteBuffer buffer_; 436*9712c20fSFrederick Mayle 437*9712c20fSFrederick Mayle // True if this file is big-endian. 438*9712c20fSFrederick Mayle bool big_endian_; 439*9712c20fSFrederick Mayle 440*9712c20fSFrederick Mayle // True if this file is a 64-bit Mach-O file. 441*9712c20fSFrederick Mayle bool bits_64_; 442*9712c20fSFrederick Mayle 443*9712c20fSFrederick Mayle // This file's cpu type and subtype. 444*9712c20fSFrederick Mayle cpu_type_t cpu_type_; // mach_header[_64].cputype 445*9712c20fSFrederick Mayle cpu_subtype_t cpu_subtype_; // mach_header[_64].cpusubtype 446*9712c20fSFrederick Mayle 447*9712c20fSFrederick Mayle // This file's type. 448*9712c20fSFrederick Mayle FileType file_type_; // mach_header[_64].filetype 449*9712c20fSFrederick Mayle 450*9712c20fSFrederick Mayle // The region of buffer_ occupied by load commands. 451*9712c20fSFrederick Mayle ByteBuffer load_commands_; 452*9712c20fSFrederick Mayle 453*9712c20fSFrederick Mayle // The number of load commands in load_commands_. 454*9712c20fSFrederick Mayle uint32_t load_command_count_; // mach_header[_64].ncmds 455*9712c20fSFrederick Mayle 456*9712c20fSFrederick Mayle // This file's header flags. 457*9712c20fSFrederick Mayle FileFlags flags_; 458*9712c20fSFrederick Mayle }; 459*9712c20fSFrederick Mayle 460*9712c20fSFrederick Mayle } // namespace mach_o 461*9712c20fSFrederick Mayle } // namespace google_breakpad 462*9712c20fSFrederick Mayle 463*9712c20fSFrederick Mayle #endif // BREAKPAD_COMMON_MAC_MACHO_READER_H_ 464