Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// Copyright 2019 Google
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
 
15
#import "Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h"
16
 
17
#include <dlfcn.h>
18
 
19
#include "Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h"
20
#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h"
21
#import "Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h"
22
#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h"
23
#import "Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h"
24
 
25
@interface FIRCLSSymbolResolver () {
26
  NSMutableArray* _binaryImages;
27
}
28
 
29
@end
30
 
31
@implementation FIRCLSSymbolResolver
32
 
33
- (instancetype)init {
34
  self = [super init];
35
  if (!self) {
36
    return nil;
37
  }
38
 
39
  _binaryImages = [NSMutableArray array];
40
 
41
  return self;
42
}
43
 
44
- (BOOL)loadBinaryImagesFromFile:(NSString*)path {
45
  if ([path length] == 0) {
46
    return NO;
47
  }
48
 
49
  NSArray* sections = FIRCLSFileReadSections([path fileSystemRepresentation], false, nil);
50
 
51
  if ([sections count] == 0) {
52
    FIRCLSErrorLog(@"Failed to read binary image file %@", path);
53
    return NO;
54
  }
55
 
56
  // filter out unloads, as well as loads with invalid entries
57
  for (NSDictionary* entry in sections) {
58
    NSDictionary* details = [entry objectForKey:@"load"];
59
    if (!details) {
60
      continue;
61
    }
62
 
63
    // This does happen occationally and causes a crash. I'm really not sure there
64
    // is anything sane we can do in this case.
65
    if (![details objectForKey:@"base"] || ![details objectForKey:@"size"]) {
66
      continue;
67
    }
68
 
69
    if ([details objectForKey:@"base"] == (id)[NSNull null] ||
70
        [details objectForKey:@"size"] == (id)[NSNull null]) {
71
      continue;
72
    }
73
 
74
    [_binaryImages addObject:details];
75
  }
76
 
77
  [_binaryImages sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
78
    NSNumber* base1 = [obj1 objectForKey:@"base"];
79
    NSNumber* base2 = [obj2 objectForKey:@"base"];
80
 
81
    return [base1 compare:base2];
82
  }];
83
 
84
  return YES;
85
}
86
 
87
- (NSDictionary*)loadedBinaryImageForPC:(uintptr_t)pc {
88
  NSUInteger index =
89
      [_binaryImages indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL* stop) {
90
        uintptr_t base = [[obj objectForKey:@"base"] unsignedIntegerValue];
91
        uintptr_t size = [[obj objectForKey:@"size"] unsignedIntegerValue];
92
 
93
        return pc >= base && pc < (base + size);
94
      }];
95
 
96
  if (index == NSNotFound) {
97
    return nil;
98
  }
99
 
100
  return [_binaryImages objectAtIndex:index];
101
}
102
 
103
- (BOOL)fillInImageDetails:(FIRCLSBinaryImageDetails*)details forUUID:(NSString*)uuid {
104
  if (!details || !uuid) {
105
    return NO;
106
  }
107
 
108
  return FIRCLSBinaryImageFindImageForUUID([uuid UTF8String], details);
109
}
110
 
111
- (FIRStackFrame*)frameForAddress:(uint64_t)address {
112
  FIRStackFrame* frame = [FIRStackFrame stackFrameWithAddress:(NSUInteger)address];
113
 
114
  if (![self updateStackFrame:frame]) {
115
    return nil;
116
  }
117
 
118
  return frame;
119
}
120
 
121
- (BOOL)updateStackFrame:(FIRStackFrame*)frame {
122
  uint64_t address = [frame address];
123
  if (address == 0) {
124
    return NO;
125
  }
126
 
127
  NSDictionary* binaryImage = [self loadedBinaryImageForPC:(uintptr_t)address];
128
 
129
  FIRCLSBinaryImageDetails imageDetails;
130
 
131
  if (![self fillInImageDetails:&imageDetails forUUID:[binaryImage objectForKey:@"uuid"]]) {
132
#if DEBUG
133
    FIRCLSSDKLog("Image not found\n");
134
#endif
135
    return NO;
136
  }
137
 
138
  uintptr_t addr = (uintptr_t)address -
139
                   (uintptr_t)[[binaryImage objectForKey:@"base"] unsignedIntegerValue] +
140
                   (uintptr_t)imageDetails.node.baseAddress;
141
  Dl_info dlInfo;
142
 
143
  if (dladdr((void*)addr, &dlInfo) == 0) {
144
#if DEBUG
145
    FIRCLSSDKLog("Could not look up address\n");
146
#endif
147
    return NO;
148
  }
149
 
150
  if (addr - (uintptr_t)dlInfo.dli_saddr == 0) {
151
    addr -= 2;
152
    if (dladdr((void*)addr, &dlInfo) == 0) {
153
#if DEBUG
154
      FIRCLSSDKLog("Could not look up address after move\n");
155
#endif
156
      return NO;
157
    }
158
  }
159
 
160
  if (dlInfo.dli_sname) {
161
    NSString* symbol = [NSString stringWithUTF8String:dlInfo.dli_sname];
162
 
163
    frame.symbol = symbol;
164
    frame.rawSymbol = symbol;
165
  }
166
 
167
  if (addr > (uintptr_t)dlInfo.dli_saddr) {
168
    [frame setOffset:addr - (uintptr_t)dlInfo.dli_saddr];
169
  }
170
 
171
  [frame setLibrary:[[binaryImage objectForKey:@"path"] lastPathComponent]];
172
 
173
  return YES;
174
}
175
 
176
@end