@@ -194,30 +194,54 @@ class Addr2LineProcess : public SymbolizerProcess {
194
194
const char *module_name () const { return module_name_; }
195
195
196
196
private:
197
- bool ReachedEndOfOutput (const char *buffer, uptr length) const override {
198
- // Output should consist of two lines.
199
- int num_lines = 0 ;
200
- for (uptr i = 0 ; i < length; ++i) {
201
- if (buffer[i] == ' \n ' )
202
- num_lines++;
203
- if (num_lines >= 2 )
204
- return true ;
205
- }
206
- return false ;
207
- }
208
-
209
197
void GetArgV (const char *path_to_binary,
210
198
const char *(&argv)[kArgVMax]) const override {
211
199
int i = 0 ;
212
200
argv[i++] = path_to_binary;
213
- argv[i++] = " -Cfe " ;
201
+ argv[i++] = " -iCfe " ;
214
202
argv[i++] = module_name_;
215
203
argv[i++] = nullptr ;
216
204
}
217
205
206
+ bool ReachedEndOfOutput (const char *buffer, uptr length) const override ;
207
+
208
+ bool ReadFromSymbolizer (char *buffer, uptr max_length) override {
209
+ if (!SymbolizerProcess::ReadFromSymbolizer (buffer, max_length))
210
+ return false ;
211
+ // We should cut out output_terminator_ at the end of given buffer,
212
+ // appended by addr2line to mark the end of its meaningful output.
213
+ // We cannot scan buffer from it's beginning, because it is legal for it
214
+ // to start with output_terminator_ in case given offset is invalid. So,
215
+ // scanning from second character.
216
+ char *garbage = internal_strstr (buffer + 1 , output_terminator_);
217
+ // This should never be NULL since buffer must end up with
218
+ // output_terminator_.
219
+ CHECK (garbage);
220
+ // Trim the buffer.
221
+ garbage[0 ] = ' \0 ' ;
222
+ return true ;
223
+ }
224
+
218
225
const char *module_name_; // Owned, leaked.
226
+ static const char output_terminator_[];
219
227
};
220
228
229
+ const char Addr2LineProcess::output_terminator_[] = " ??\n ??:0\n " ;
230
+
231
+ bool Addr2LineProcess::ReachedEndOfOutput (const char *buffer,
232
+ uptr length) const {
233
+ const size_t kTerminatorLen = sizeof (output_terminator_) - 1 ;
234
+ // Skip, if we read just kTerminatorLen bytes, because Addr2Line output
235
+ // should consist at least of two pairs of lines:
236
+ // 1. First one, corresponding to given offset to be symbolized
237
+ // (may be equal to output_terminator_, if offset is not valid).
238
+ // 2. Second one for output_terminator_, itself to mark the end of output.
239
+ if (length <= kTerminatorLen ) return false ;
240
+ // Addr2Line output should end up with output_terminator_.
241
+ return !internal_memcmp (buffer + length - kTerminatorLen ,
242
+ output_terminator_, kTerminatorLen );
243
+ }
244
+
221
245
class Addr2LinePool : public SymbolizerTool {
222
246
public:
223
247
explicit Addr2LinePool (const char *addr2line_path,
@@ -254,15 +278,18 @@ class Addr2LinePool : public SymbolizerTool {
254
278
addr2line_pool_.push_back (addr2line);
255
279
}
256
280
CHECK_EQ (0 , internal_strcmp (module_name, addr2line->module_name ()));
257
- char buffer_[kBufferSize ];
258
- internal_snprintf (buffer_, kBufferSize , " 0x%zx\n " , module_offset);
259
- return addr2line->SendCommand (buffer_);
281
+ char buffer[kBufferSize ];
282
+ internal_snprintf (buffer, kBufferSize , " 0x%zx\n 0x%zx\n " ,
283
+ module_offset, dummy_address_);
284
+ return addr2line->SendCommand (buffer);
260
285
}
261
286
262
- static const uptr kBufferSize = 32 ;
287
+ static const uptr kBufferSize = 64 ;
263
288
const char *addr2line_path_;
264
289
LowLevelAllocator *allocator_;
265
290
InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
291
+ static const uptr dummy_address_ =
292
+ FIRST_32_SECOND_64 (UINT32_MAX, UINT64_MAX);
266
293
};
267
294
268
295
#if SANITIZER_SUPPORTS_WEAK_HOOKS
0 commit comments