aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNelson Billing <nbilling@google.com>2020-08-14 18:32:45 -0700
committerNelson Billing <nbilling@google.com>2020-08-17 22:31:50 +0000
commit9c38ab7c67e5b199e6b7ffafa27b7f463f06dedd (patch)
tree5f6081b3dc47eef23accaa325ff1aa0b5c043c36
parentlinux: Fix segfault when there is no section header in ELF file (diff)
downloadbreakpad-9c38ab7c67e5b199e6b7ffafa27b7f463f06dedd.tar.xz
Add native symbol uploads to Mac OS symupload tool.
- sym-upload-v2 protocol only. - Supports elf, dwp, debug_only, macho, dsym, pe, and pdb (with the classic mode being called 'breakpad'). Change-Id: I68c0065aec3a7ffe29b364dd9e2e1dbdb58e3e5d Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/2357528 Reviewed-by: Mark Mentovai <mark@chromium.org>
-rw-r--r--src/common/mac/SymbolCollectorClient.h3
-rw-r--r--src/common/mac/SymbolCollectorClient.m12
-rw-r--r--src/tools/mac/symupload/symupload.m142
3 files changed, 127 insertions, 30 deletions
diff --git a/src/common/mac/SymbolCollectorClient.h b/src/common/mac/SymbolCollectorClient.h
index 1f27f23f..9e955c8e 100644
--- a/src/common/mac/SymbolCollectorClient.h
+++ b/src/common/mac/SymbolCollectorClient.h
@@ -95,7 +95,8 @@ typedef NS_ENUM(NSInteger, SymbolStatus) {
withAPIKey:(NSString*)APIKey
withUploadKey:(NSString*)uploadKey
withDebugFile:(NSString*)debugFile
- withDebugID:(NSString*)debugID;
+ withDebugID:(NSString*)debugID
+ withType:(NSString*)type;
@end
diff --git a/src/common/mac/SymbolCollectorClient.m b/src/common/mac/SymbolCollectorClient.m
index f7cd9235..b135cdeb 100644
--- a/src/common/mac/SymbolCollectorClient.m
+++ b/src/common/mac/SymbolCollectorClient.m
@@ -77,9 +77,9 @@
[allowedDebugFileCharacters
formUnionWithCharacterSet:[NSCharacterSet controlCharacterSet]];
[allowedDebugFileCharacters invert];
- NSString* escapedDebugFile = [debugFile
- stringByAddingPercentEncodingWithAllowedCharacters:
- allowedDebugFileCharacters];
+ NSString* escapedDebugFile =
+ [debugFile stringByAddingPercentEncodingWithAllowedCharacters:
+ allowedDebugFileCharacters];
NSURL* URL = [NSURL
URLWithString:[NSString
@@ -189,7 +189,8 @@
withAPIKey:(NSString*)APIKey
withUploadKey:(NSString*)uploadKey
withDebugFile:(NSString*)debugFile
- withDebugID:(NSString*)debugID {
+ withDebugID:(NSString*)debugID
+ withType:(NSString*)type {
NSURL* URL = [NSURL
URLWithString:[NSString
stringWithFormat:@"%@/v1/uploads/%@:complete?key=%@",
@@ -199,7 +200,8 @@
[NSDictionary dictionaryWithObjectsAndKeys:debugFile, @"debug_file",
debugID, @"debug_id", nil];
NSDictionary* jsonDictionary = [NSDictionary
- dictionaryWithObjectsAndKeys:symbolIdDictionary, @"symbol_id", nil];
+ dictionaryWithObjectsAndKeys:symbolIdDictionary, @"symbol_id", type,
+ @"symbol_upload_type", nil];
NSError* error;
NSData* jsonData =
[NSJSONSerialization dataWithJSONObject:jsonDictionary
diff --git a/src/tools/mac/symupload/symupload.m b/src/tools/mac/symupload/symupload.m
index 2c663fe1..61c2450d 100644
--- a/src/tools/mac/symupload/symupload.m
+++ b/src/tools/mac/symupload/symupload.m
@@ -48,6 +48,8 @@
#include "HTTPPutRequest.h"
#include "SymbolCollectorClient.h"
+NSString* const kBreakpadSymbolType = @"BREAKPAD";
+
typedef enum { kSymUploadProtocolV1, kSymUploadProtocolV2 } SymUploadProtocol;
typedef enum {
@@ -63,6 +65,9 @@ typedef struct {
NSString* apiKey;
BOOL force;
Result result;
+ NSString* type;
+ NSString* codeFile;
+ NSString* debugID;
} Options;
//=============================================================================
@@ -100,21 +105,20 @@ static NSArray* ModuleDataForSymbolFile(NSString* file) {
//=============================================================================
static void StartSymUploadProtocolV1(Options* options,
- NSArray* moduleParts,
- NSString* compactedID) {
+ NSString* OS,
+ NSString* CPU,
+ NSString* debugID,
+ NSString* debugFile) {
NSURL* url = [NSURL URLWithString:options->uploadURLStr];
HTTPMultipartUpload* ul = [[HTTPMultipartUpload alloc] initWithURL:url];
NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
// Add parameters
- [parameters setObject:compactedID forKey:@"debug_identifier"];
-
- // MODULE <os> <cpu> <uuid> <module-name>
- // 0 1 2 3 4
- [parameters setObject:[moduleParts objectAtIndex:1] forKey:@"os"];
- [parameters setObject:[moduleParts objectAtIndex:2] forKey:@"cpu"];
- [parameters setObject:[moduleParts objectAtIndex:4] forKey:@"debug_file"];
- [parameters setObject:[moduleParts objectAtIndex:4] forKey:@"code_file"];
+ [parameters setObject:debugID forKey:@"debug_identifier"];
+ [parameters setObject:OS forKey:@"os"];
+ [parameters setObject:CPU forKey:@"cpu"];
+ [parameters setObject:debugFile forKey:@"debug_file"];
+ [parameters setObject:debugFile forKey:@"code_file"];
[ul setParameters:parameters];
NSArray* keys = [parameters allKeys];
@@ -148,12 +152,13 @@ static void StartSymUploadProtocolV1(Options* options,
//=============================================================================
static void StartSymUploadProtocolV2(Options* options,
- NSArray* moduleParts,
- NSString* debugID) {
+ NSString* debugID,
+ NSString* debugFile) {
options->result = kResultFailure;
- NSString* debugFile = [moduleParts objectAtIndex:4];
- if (!options->force) {
+ // Only check status of BREAKPAD symbols, because the v2 protocol doesn't
+ // (yet) have a way to check status of other symbol types.
+ if (!options->force && [options->type isEqualToString:kBreakpadSymbolType]) {
SymbolStatus symbolStatus =
[SymbolCollectorClient checkSymbolStatusOnServer:options->uploadURLStr
withAPIKey:options->apiKey
@@ -201,7 +206,8 @@ static void StartSymUploadProtocolV2(Options* options,
withAPIKey:options->apiKey
withUploadKey:[URLResponse uploadKey]
withDebugFile:debugFile
- withDebugID:debugID];
+ withDebugID:debugID
+ withType:options->type];
[URLResponse release];
if (completeUploadResult == CompleteUploadResultError) {
fprintf(stdout, "Failed to complete upload.\n");
@@ -217,18 +223,29 @@ static void StartSymUploadProtocolV2(Options* options,
//=============================================================================
static void Start(Options* options) {
+ // If non-BREAKPAD upload special-case.
+ if (![options->type isEqualToString:kBreakpadSymbolType]) {
+ StartSymUploadProtocolV2(options, options->debugID, options->codeFile);
+ return;
+ }
+
NSArray* moduleParts = ModuleDataForSymbolFile(options->symbolsPath);
- NSMutableString* compactedID =
+ // MODULE <os> <cpu> <uuid> <module-name>
+ // 0 1 2 3 4
+ NSString* OS = [moduleParts objectAtIndex:1];
+ NSString* CPU = [moduleParts objectAtIndex:2];
+ NSMutableString* debugID =
[NSMutableString stringWithString:[moduleParts objectAtIndex:3]];
- [compactedID replaceOccurrencesOfString:@"-"
- withString:@""
- options:0
- range:NSMakeRange(0, [compactedID length])];
+ [debugID replaceOccurrencesOfString:@"-"
+ withString:@""
+ options:0
+ range:NSMakeRange(0, [debugID length])];
+ NSString* debugFile = [moduleParts objectAtIndex:4];
if (options->symUploadProtocol == kSymUploadProtocolV1) {
- StartSymUploadProtocolV1(options, moduleParts, compactedID);
+ StartSymUploadProtocolV1(options, OS, CPU, debugID, debugFile);
} else if (options->symUploadProtocol == kSymUploadProtocolV2) {
- StartSymUploadProtocolV2(options, moduleParts, compactedID);
+ StartSymUploadProtocolV2(options, debugID, debugFile);
}
}
@@ -247,8 +264,21 @@ static void Usage(int argc, const char* argv[]) {
"server. [Only in sym-upload-v2 protocol mode]\n");
fprintf(stderr, "\t-f: Overwrite symbol file on server if already present. "
"[Only in sym-upload-v2 protocol mode]\n");
+ fprintf(
+ stderr,
+ "-t:\t <symbol-type> Explicitly set symbol upload type ("
+ "default is 'breakpad').\n"
+ "\t One of ['breakpad', 'elf', 'pe', 'macho', 'debug_only', 'dwp', "
+ "'dsym', 'pdb'].\n"
+ "\t Note: When this flag is set to anything other than 'breakpad', then "
+ "the '-c' and '-i' flags must also be set.\n");
+ fprintf(stderr, "-c:\t <code-file> Explicitly set 'code_file' for symbol "
+ "upload (basename of executable).\n");
+ fprintf(stderr, "-i:\t <debug-id> Explicitly set 'debug_id' for symbol "
+ "upload (typically build ID of executable).\n");
fprintf(stderr, "\t-h: Usage\n");
fprintf(stderr, "\t-?: Usage\n");
+ fprintf(stderr, "\n");
fprintf(stderr, "Exit codes:\n");
fprintf(stderr, "\t%d: Success\n", kResultSuccess);
fprintf(stderr, "\t%d: Failure\n", kResultFailure);
@@ -264,17 +294,39 @@ static void Usage(int argc, const char* argv[]) {
"Failure\n");
fprintf(stderr, "\t in this case, and the action taken by the server is "
"unspecified.]\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Examples:\n");
+ fprintf(stderr, " With 'sym-upload-v1':\n");
+ fprintf(stderr, " %s path/to/symbol_file http://myuploadserver\n",
+ argv[0]);
+ fprintf(stderr, " With 'sym-upload-v2':\n");
+ fprintf(stderr, " [Defaulting to symbol type 'BREAKPAD']\n");
+ fprintf(stderr,
+ " %s -p sym-upload-v2 -k mysecret123! "
+ "path/to/symbol_file http://myuploadserver\n",
+ argv[0]);
+ fprintf(stderr, " [Explicitly set symbol type to 'macho']\n");
+ fprintf(stderr,
+ " %s -p sym-upload-v2 -k mysecret123! -t macho "
+ "-c app -i 11111111BBBB3333DDDD555555555555F "
+ "path/to/symbol_file http://myuploadserver\n",
+ argv[0]);
}
//=============================================================================
static void SetupOptions(int argc, const char* argv[], Options* options) {
- // Set default value of symUploadProtocol.
+ // Set default options values.
options->symUploadProtocol = kSymUploadProtocolV1;
+ options->apiKey = nil;
+ options->type = kBreakpadSymbolType;
+ options->codeFile = nil;
+ options->debugID = nil;
+ options->force = NO;
extern int optind;
char ch;
- while ((ch = getopt(argc, (char* const*)argv, "p:k:hf?")) != -1) {
+ while ((ch = getopt(argc, (char* const*)argv, "p:k:t:c:i:hf?")) != -1) {
switch (ch) {
case 'p':
if (strcmp(optarg, "sym-upload-v2") == 0) {
@@ -292,6 +344,24 @@ static void SetupOptions(int argc, const char* argv[], Options* options) {
options->apiKey = [NSString stringWithCString:optarg
encoding:NSASCIIStringEncoding];
break;
+ case 't': {
+ // This is really an enum, so treat as upper-case for consistency with
+ // enum naming convention on server-side.
+ options->type = [[NSString stringWithCString:optarg
+ encoding:NSASCIIStringEncoding]
+ uppercaseString];
+ break;
+ }
+ case 'c':
+ options->codeFile = [NSString stringWithCString:optarg
+ encoding:NSASCIIStringEncoding];
+ ;
+ break;
+ case 'i':
+ options->debugID = [NSString stringWithCString:optarg
+ encoding:NSASCIIStringEncoding];
+ ;
+ break;
case 'f':
options->force = YES;
break;
@@ -327,6 +397,30 @@ static void SetupOptions(int argc, const char* argv[], Options* options) {
exit(1);
}
+ bool isBreakpadUpload = [options->type isEqualToString:kBreakpadSymbolType];
+ bool hasCodeFile = options->codeFile != nil;
+ bool hasDebugID = options->debugID != nil;
+ if (isBreakpadUpload && (hasCodeFile || hasDebugID)) {
+ fprintf(stderr, "\n");
+ fprintf(stderr,
+ "%s: -c and -i should only be specified for non-breakpad "
+ "symbol upload types.\n",
+ argv[0]);
+ fprintf(stderr, "\n");
+ Usage(argc, argv);
+ exit(1);
+ }
+ if (!isBreakpadUpload && (!hasCodeFile || !hasDebugID)) {
+ fprintf(stderr, "\n");
+ fprintf(stderr,
+ "%s: -c and -i must be specified for non-breakpad "
+ "symbol upload types.\n",
+ argv[0]);
+ fprintf(stderr, "\n");
+ Usage(argc, argv);
+ exit(1);
+ }
+
options->symbolsPath = [NSString stringWithUTF8String:argv[optind]];
options->uploadURLStr = [NSString stringWithUTF8String:argv[optind + 1]];
}