Chromium Code Reviews| Index: src/common/mac/dump_syms.cc |
| diff --git a/src/common/mac/dump_syms.mm b/src/common/mac/dump_syms.cc |
| similarity index 88% |
| rename from src/common/mac/dump_syms.mm |
| rename to src/common/mac/dump_syms.cc |
| index 58cf4c208ae4220fe9eedb97ccd4189d6f5588a0..8f490f971d5e9df1b8d4dbdb776b50522af2a616 100644 |
| --- a/src/common/mac/dump_syms.mm |
| +++ b/src/common/mac/dump_syms.cc |
| @@ -36,10 +36,12 @@ |
| #include "common/mac/dump_syms.h" |
| #include <assert.h> |
| -#include <Foundation/Foundation.h> |
| +#include <libgen.h> |
| #include <mach-o/arch.h> |
| #include <mach-o/fat.h> |
| #include <stdio.h> |
| +#include <sys/stat.h> |
| +#include <unistd.h> |
| #include <ostream> |
| #include <string> |
| @@ -85,19 +87,20 @@ using std::vector; |
| namespace google_breakpad { |
| -bool DumpSymbols::Read(NSString *filename) { |
| - if (![[NSFileManager defaultManager] fileExistsAtPath:filename]) { |
| +bool DumpSymbols::Read(const string &filename) { |
| + struct stat st; |
| + if (stat(filename.c_str(), &st) == -1) { |
| fprintf(stderr, "Object file does not exist: %s\n", |
|
Mark Mentovai
2015/09/11 15:49:50
Not necessarily—use strerror(errno) for the real e
Ted Mielczarek
2015/09/15 12:58:36
Done.
|
| - [filename fileSystemRepresentation]); |
| + filename.c_str()); |
| return false; |
| } |
| - input_pathname_ = [filename retain]; |
| + input_pathname_ = filename; |
| // Does this filename refer to a dSYM bundle? |
| - NSBundle *bundle = [NSBundle bundleWithPath:input_pathname_]; |
| - |
| - if (bundle) { |
| + string contents_path = input_pathname_ + "/Contents/Resources/DWARF"; |
| + if (S_ISDIR(st.st_mode) && |
| + access(contents_path.c_str(), F_OK) == 0) { |
| // Filenames referring to bundles usually have names of the form |
|
Mark Mentovai
2015/09/11 15:49:50
This is totally hokey. It seems to break down if t
Ted Mielczarek
2015/09/15 12:58:36
Done.
|
| // "<basename>.dSYM"; however, if the user has specified a wrapper |
| // suffix (the WRAPPER_SUFFIX and WRAPPER_EXTENSION build settings), |
| @@ -107,65 +110,62 @@ bool DumpSymbols::Read(NSString *filename) { |
| // |
| // Since there's no way to tell how much to strip off, remove one |
| // extension at a time, and use the first one that |
| - // pathForResource:ofType:inDirectory likes. |
| - NSString *base_name = [input_pathname_ lastPathComponent]; |
| - NSString *dwarf_resource; |
| + // exists under Contents/Resources/DWARF. |
| + string base_name = input_pathname_; |
| + base_name = basename(&base_name[0]); |
| - do { |
| - NSString *new_base_name = [base_name stringByDeletingPathExtension]; |
| + string dwarf_resource; |
| - // If stringByDeletingPathExtension returned the name unchanged, then |
| - // there's nothing more for us to strip off --- lose. |
| - if ([new_base_name isEqualToString:base_name]) { |
| + do { |
| + size_t lastindex = base_name.find_last_of("."); |
| + if (lastindex == string::npos) { |
| + // there's nothing more for us to strip off --- lose. |
| fprintf(stderr, "Unable to find DWARF-bearing file in bundle: %s\n", |
| - [input_pathname_ fileSystemRepresentation]); |
| + input_pathname_.c_str()); |
| return false; |
| } |
| // Take the shortened result as our new base_name. |
| - base_name = new_base_name; |
| + base_name = base_name.substr(0, lastindex); |
| // Try to find a DWARF resource in the bundle under the new base_name. |
| - dwarf_resource = [bundle pathForResource:base_name |
| - ofType:nil inDirectory:@"DWARF"]; |
| - } while (!dwarf_resource); |
| + dwarf_resource = contents_path + "/" + base_name; |
| + } while (access(dwarf_resource.c_str(), F_OK) == -1); |
| - object_filename_ = [dwarf_resource retain]; |
| + object_filename_ = dwarf_resource; |
| } else { |
| - object_filename_ = [input_pathname_ retain]; |
| + object_filename_ = input_pathname_; |
| } |
| // Read the file's contents into memory. |
| - // |
| - // The documentation for dataWithContentsOfMappedFile says: |
| - // |
| - // Because of file mapping restrictions, this method should only be |
| - // used if the file is guaranteed to exist for the duration of the |
| - // data object’s existence. It is generally safer to use the |
| - // dataWithContentsOfFile: method. |
| - // |
| - // I gather this means that OS X doesn't have (or at least, that method |
| - // doesn't use) a form of mapping like Linux's MAP_PRIVATE, where the |
| - // process appears to get its own copy of the data, and changes to the |
| - // file don't affect memory and vice versa). |
| - NSError *error; |
| - contents_ = [NSData dataWithContentsOfFile:object_filename_ |
| - options:0 |
| - error:&error]; |
| - if (!contents_) { |
| + bool read_ok = false; |
| + string error; |
| + if (stat(object_filename_.c_str(), &st) != -1) { |
| + FILE* f = fopen(object_filename_.c_str(), "rb"); |
| + if (f) { |
| + contents_.resize(st.st_size); |
| + read_ok = (fread(&contents_[0], st.st_size, 1, f) == 1); |
|
Mark Mentovai
2015/09/11 15:49:50
No read loop?
Generally it’s preferable to read u
Ted Mielczarek
2015/09/15 12:58:36
Done.
|
| + if (!read_ok) { |
| + error = strerror(errno); |
| + } |
| + fclose(f); |
| + } else { |
| + error = strerror(errno); |
| + } |
| + } |
| + |
| + if (!read_ok) { |
| fprintf(stderr, "Error reading object file: %s: %s\n", |
| - [object_filename_ fileSystemRepresentation], |
| - [[error localizedDescription] UTF8String]); |
| + object_filename_.c_str(), |
| + error.c_str()); |
| return false; |
| } |
| - [contents_ retain]; |
| // Get the list of object files present in the file. |
| - FatReader::Reporter fat_reporter([object_filename_ |
| - fileSystemRepresentation]); |
| + FatReader::Reporter fat_reporter(object_filename_); |
| FatReader fat_reader(&fat_reporter); |
| - if (!fat_reader.Read(reinterpret_cast<const uint8_t *>([contents_ bytes]), |
| - [contents_ length])) { |
| + if (!fat_reader.Read(&contents_[0], |
| + contents_.size())) { |
| return false; |
| } |
| @@ -175,7 +175,7 @@ bool DumpSymbols::Read(NSString *filename) { |
| fat_reader.object_files(&object_files_count); |
| if (object_files_count == 0) { |
| fprintf(stderr, "Fat binary file contains *no* architectures: %s\n", |
| - [object_filename_ fileSystemRepresentation]); |
| + object_filename_.c_str()); |
| return false; |
| } |
| object_files_.resize(object_files_count); |
| @@ -258,13 +258,13 @@ SuperFatArch* DumpSymbols::FindBestMatchForArchitecture( |
| } |
| string DumpSymbols::Identifier() { |
| - FileID file_id([object_filename_ fileSystemRepresentation]); |
| + FileID file_id(object_filename_.c_str()); |
| unsigned char identifier_bytes[16]; |
| cpu_type_t cpu_type = selected_object_file_->cputype; |
| cpu_subtype_t cpu_subtype = selected_object_file_->cpusubtype; |
| if (!file_id.MachoIdentifier(cpu_type, cpu_subtype, identifier_bytes)) { |
| fprintf(stderr, "Unable to calculate UUID of mach-o binary %s!\n", |
| - [object_filename_ fileSystemRepresentation]); |
| + object_filename_.c_str()); |
| return ""; |
| } |
| @@ -526,7 +526,7 @@ bool DumpSymbols::ReadSymbolData(Module** out_module) { |
| " architecture, none of which match the current" |
| " architecture; specify an architecture explicitly" |
| " with '-a ARCH' to resolve the ambiguity\n", |
| - [object_filename_ fileSystemRepresentation]); |
| + object_filename_.c_str()); |
| return false; |
| } |
| } |
| @@ -546,14 +546,15 @@ bool DumpSymbols::ReadSymbolData(Module** out_module) { |
| // Produce a name to use in error messages that includes the |
| // filename, and the architecture, if there is more than one. |
| - selected_object_name_ = [object_filename_ UTF8String]; |
| + selected_object_name_ = object_filename_; |
| if (object_files_.size() > 1) { |
| selected_object_name_ += ", architecture "; |
| selected_object_name_ + selected_arch_name; |
| } |
| // Compute a module name, to appear in the MODULE record. |
| - NSString *module_name = [object_filename_ lastPathComponent]; |
| + string module_name = object_filename_; |
| + module_name = basename(&module_name[0]); |
| // Choose an identifier string, to appear in the MODULE record. |
| string identifier = Identifier(); |
| @@ -562,7 +563,7 @@ bool DumpSymbols::ReadSymbolData(Module** out_module) { |
| identifier += "0"; |
| // Create a module to hold the debugging information. |
| - scoped_ptr<Module> module(new Module([module_name UTF8String], |
| + scoped_ptr<Module> module(new Module(module_name, |
| "mac", |
| selected_arch_name, |
| identifier)); |
| @@ -570,7 +571,7 @@ bool DumpSymbols::ReadSymbolData(Module** out_module) { |
| // Parse the selected object file. |
| mach_o::Reader::Reporter reporter(selected_object_name_); |
| mach_o::Reader reader(&reporter); |
| - if (!reader.Read(reinterpret_cast<const uint8_t *>([contents_ bytes]) |
| + if (!reader.Read(&contents_[0] |
| + selected_object_file_->offset, |
| selected_object_file_->size, |
| selected_object_file_->cputype, |