aboutsummaryrefslogtreecommitdiff
path: root/src/processor/basic_source_line_resolver.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/processor/basic_source_line_resolver.cc')
-rw-r--r--src/processor/basic_source_line_resolver.cc377
1 files changed, 323 insertions, 54 deletions
diff --git a/src/processor/basic_source_line_resolver.cc b/src/processor/basic_source_line_resolver.cc
index c4aa949c..07aba6bc 100644
--- a/src/processor/basic_source_line_resolver.cc
+++ b/src/processor/basic_source_line_resolver.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2010 Google Inc.
-// All rights reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
-// * Neither the name of Google Inc. nor the names of its
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -40,6 +39,7 @@
#include <limits>
#include <map>
+#include <memory>
#include <utility>
#include <vector>
@@ -49,9 +49,11 @@
#include "processor/tokenize.h"
+using std::deque;
+using std::make_pair;
using std::map;
+using std::unique_ptr;
using std::vector;
-using std::make_pair;
namespace google_breakpad {
@@ -69,11 +71,11 @@ namespace {
// field, and max_tokens is the maximum number of tokens including the optional
// field. Refer to the documentation for Tokenize for descriptions of the other
// arguments.
-bool TokenizeWithOptionalField(char *line,
- const char *optional_field,
- const char *separators,
+bool TokenizeWithOptionalField(char* line,
+ const char* optional_field,
+ const char* separators,
int max_tokens,
- vector<char*> *tokens) {
+ vector<char*>* tokens) {
// First tokenize assuming the optional field is not present. If we then see
// the optional field, additionally tokenize the last token into two tokens.
if (!Tokenize(line, separators, max_tokens - 1, tokens)) {
@@ -98,7 +100,7 @@ bool TokenizeWithOptionalField(char *line,
} // namespace
-static const char *kWhitespace = " \r\n";
+static const char* kWhitespace = " \r\n";
static const int kMaxErrorsPrinted = 5;
static const int kMaxErrorsBeforeBailing = 100;
@@ -107,9 +109,9 @@ BasicSourceLineResolver::BasicSourceLineResolver() :
// static
void BasicSourceLineResolver::Module::LogParseError(
- const string &message,
+ const string& message,
int line_number,
- int *num_errors) {
+ int* num_errors) {
if (++(*num_errors) <= kMaxErrorsPrinted) {
if (line_number > 0) {
BPLOG(ERROR) << "Line " << line_number << ": " << message;
@@ -120,12 +122,13 @@ void BasicSourceLineResolver::Module::LogParseError(
}
bool BasicSourceLineResolver::Module::LoadMapFromMemory(
- char *memory_buffer,
+ char* memory_buffer,
size_t memory_buffer_size) {
linked_ptr<Function> cur_func;
int line_number = 0;
int num_errors = 0;
- char *save_ptr;
+ int inline_num_errors = 0;
+ char* save_ptr;
// If the length is 0, we can still pretend we have a symbol file. This is
// for scenarios that want to test symbol lookup, but don't necessarily care
@@ -160,7 +163,7 @@ bool BasicSourceLineResolver::Module::LoadMapFromMemory(
&num_errors);
}
- char *buffer;
+ char* buffer;
buffer = strtok_r(memory_buffer, "\r\n", &save_ptr);
while (buffer != NULL) {
@@ -202,12 +205,23 @@ bool BasicSourceLineResolver::Module::LoadMapFromMemory(
// Ignore these as well, they're similarly just for housekeeping.
//
// INFO CODE_ID <code id> <filename>
+ } else if (strncmp(buffer, "INLINE ", 7) == 0) {
+ linked_ptr<Inline> in = ParseInline(buffer);
+ if (!in.get())
+ LogParseError("ParseInline failed", line_number, &inline_num_errors);
+ else
+ cur_func->AppendInline(in);
+ } else if (strncmp(buffer, "INLINE_ORIGIN ", 14) == 0) {
+ if (!ParseInlineOrigin(buffer)) {
+ LogParseError("ParseInlineOrigin failed", line_number,
+ &inline_num_errors);
+ }
} else {
if (!cur_func.get()) {
LogParseError("Found source line data without a function",
line_number, &num_errors);
} else {
- Line *line = ParseLine(buffer);
+ Line* line = ParseLine(buffer);
if (!line) {
LogParseError("ParseLine failed", line_number, &num_errors);
} else {
@@ -225,7 +239,67 @@ bool BasicSourceLineResolver::Module::LoadMapFromMemory(
return true;
}
-void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
+void BasicSourceLineResolver::Module::ConstructInlineFrames(
+ StackFrame* frame,
+ MemAddr address,
+ const ContainedRangeMap<uint64_t, linked_ptr<Inline>>& inline_map,
+ deque<unique_ptr<StackFrame>>* inlined_frames) const {
+ vector<const linked_ptr<Inline>*> inlines;
+ if (!inline_map.RetrieveRanges(address, inlines)) {
+ return;
+ }
+
+ for (const linked_ptr<Inline>* const in : inlines) {
+ unique_ptr<StackFrame> new_frame =
+ unique_ptr<StackFrame>(new StackFrame(*frame));
+ auto origin = inline_origins_.find(in->get()->origin_id);
+ if (origin != inline_origins_.end()) {
+ new_frame->function_name = origin->second->name;
+ } else {
+ new_frame->function_name = "<name omitted>";
+ }
+
+ // Store call site file and line in current frame, which will be updated
+ // later.
+ new_frame->source_line = in->get()->call_site_line;
+ if (in->get()->has_call_site_file_id) {
+ auto file = files_.find(in->get()->call_site_file_id);
+ if (file != files_.end()) {
+ new_frame->source_file_name = file->second;
+ }
+ }
+
+ // Use the starting address of the inlined range as inlined function base.
+ new_frame->function_base = new_frame->module->base_address();
+ for (const auto& range : in->get()->inline_ranges) {
+ if (address >= range.first && address < range.first + range.second) {
+ new_frame->function_base += range.first;
+ break;
+ }
+ }
+ new_frame->trust = StackFrame::FRAME_TRUST_INLINE;
+
+ // The inlines vector has an order from innermost entry to outermost entry.
+ // By push_back, we will have inlined_frames with the same order.
+ inlined_frames->push_back(std::move(new_frame));
+ }
+
+ // Update the source file and source line for each inlined frame.
+ if (!inlined_frames->empty()) {
+ string parent_frame_source_file_name = frame->source_file_name;
+ int parent_frame_source_line = frame->source_line;
+ frame->source_file_name = inlined_frames->back()->source_file_name;
+ frame->source_line = inlined_frames->back()->source_line;
+ for (unique_ptr<StackFrame>& inlined_frame : *inlined_frames) {
+ std::swap(inlined_frame->source_file_name, parent_frame_source_file_name);
+ std::swap(inlined_frame->source_line, parent_frame_source_line);
+ }
+ }
+}
+
+void BasicSourceLineResolver::Module::LookupAddress(
+ StackFrame* frame,
+ deque<unique_ptr<StackFrame>>* inlined_frames) const {
MemAddr address = frame->instruction - frame->module->base_address();
// First, look for a FUNC record that covers address. Use
@@ -244,6 +318,7 @@ void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
address >= function_base && address - function_base < function_size) {
frame->function_name = func->name;
frame->function_base = frame->module->base_address() + function_base;
+ frame->is_multiple = func->is_multiple;
linked_ptr<Line> line;
MemAddr line_base;
@@ -256,16 +331,22 @@ void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
frame->source_line = line->line;
frame->source_line_base = frame->module->base_address() + line_base;
}
+
+ // Check if this is inlined function call.
+ if (inlined_frames) {
+ ConstructInlineFrames(frame, address, func->inlines, inlined_frames);
+ }
} else if (public_symbols_.Retrieve(address,
&public_symbol, &public_address) &&
(!func.get() || public_address > function_base)) {
frame->function_name = public_symbol->name;
frame->function_base = frame->module->base_address() + public_address;
+ frame->is_multiple = public_symbol->is_multiple;
}
}
-WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo(
- const StackFrame *frame) const {
+WindowsFrameInfo* BasicSourceLineResolver::Module::FindWindowsFrameInfo(
+ const StackFrame* frame) const {
MemAddr address = frame->instruction - frame->module->base_address();
scoped_ptr<WindowsFrameInfo> result(new WindowsFrameInfo());
@@ -313,8 +394,8 @@ WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo(
return NULL;
}
-CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo(
- const StackFrame *frame) const {
+CFIFrameInfo* BasicSourceLineResolver::Module::FindCFIFrameInfo(
+ const StackFrame* frame) const {
MemAddr address = frame->instruction - frame->module->base_address();
MemAddr initial_base, initial_size;
string initial_rules;
@@ -347,9 +428,9 @@ CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo(
return rules.release();
}
-bool BasicSourceLineResolver::Module::ParseFile(char *file_line) {
+bool BasicSourceLineResolver::Module::ParseFile(char* file_line) {
long index;
- char *filename;
+ char* filename;
if (SymbolParseHelper::ParseFile(file_line, &index, &filename)) {
files_.insert(make_pair(index, string(filename)));
return true;
@@ -357,13 +438,48 @@ bool BasicSourceLineResolver::Module::ParseFile(char *file_line) {
return false;
}
+bool BasicSourceLineResolver::Module::ParseInlineOrigin(
+ char* inline_origin_line) {
+ bool has_file_id;
+ long origin_id;
+ long source_file_id;
+ char* origin_name;
+ if (SymbolParseHelper::ParseInlineOrigin(inline_origin_line, &has_file_id,
+ &origin_id, &source_file_id,
+ &origin_name)) {
+ inline_origins_.insert(make_pair(
+ origin_id,
+ new InlineOrigin(has_file_id, source_file_id, origin_name)));
+ return true;
+ }
+ return false;
+}
+
+linked_ptr<BasicSourceLineResolver::Inline>
+BasicSourceLineResolver::Module::ParseInline(char* inline_line) {
+ bool has_call_site_file_id;
+ long inline_nest_level;
+ long call_site_line;
+ long call_site_file_id;
+ long origin_id;
+ vector<std::pair<MemAddr, MemAddr>> ranges;
+ if (SymbolParseHelper::ParseInline(inline_line, &has_call_site_file_id,
+ &inline_nest_level, &call_site_line,
+ &call_site_file_id, &origin_id, &ranges)) {
+ return linked_ptr<Inline>(new Inline(has_call_site_file_id,
+ inline_nest_level, call_site_line,
+ call_site_file_id, origin_id, ranges));
+ }
+ return linked_ptr<Inline>();
+}
+
BasicSourceLineResolver::Function*
-BasicSourceLineResolver::Module::ParseFunction(char *function_line) {
+BasicSourceLineResolver::Module::ParseFunction(char* function_line) {
bool is_multiple;
uint64_t address;
uint64_t size;
long stack_param_size;
- char *name;
+ char* name;
if (SymbolParseHelper::ParseFunction(function_line, &is_multiple, &address,
&size, &stack_param_size, &name)) {
return new Function(name, address, size, stack_param_size, is_multiple);
@@ -372,7 +488,7 @@ BasicSourceLineResolver::Module::ParseFunction(char *function_line) {
}
BasicSourceLineResolver::Line* BasicSourceLineResolver::Module::ParseLine(
- char *line_line) {
+ char* line_line) {
uint64_t address;
uint64_t size;
long line_number;
@@ -385,11 +501,11 @@ BasicSourceLineResolver::Line* BasicSourceLineResolver::Module::ParseLine(
return NULL;
}
-bool BasicSourceLineResolver::Module::ParsePublicSymbol(char *public_line) {
+bool BasicSourceLineResolver::Module::ParsePublicSymbol(char* public_line) {
bool is_multiple;
uint64_t address;
long stack_param_size;
- char *name;
+ char* name;
if (SymbolParseHelper::ParsePublicSymbol(public_line, &is_multiple, &address,
&stack_param_size, &name)) {
@@ -411,7 +527,7 @@ bool BasicSourceLineResolver::Module::ParsePublicSymbol(char *public_line) {
return false;
}
-bool BasicSourceLineResolver::Module::ParseStackInfo(char *stack_info_line) {
+bool BasicSourceLineResolver::Module::ParseStackInfo(char* stack_info_line) {
// Skip "STACK " prefix.
stack_info_line += 6;
@@ -419,7 +535,7 @@ bool BasicSourceLineResolver::Module::ParseStackInfo(char *stack_info_line) {
// information this is.
while (*stack_info_line == ' ')
stack_info_line++;
- const char *platform = stack_info_line;
+ const char* platform = stack_info_line;
while (!strchr(kWhitespace, *stack_info_line))
stack_info_line++;
*stack_info_line++ = '\0';
@@ -468,23 +584,23 @@ bool BasicSourceLineResolver::Module::ParseStackInfo(char *stack_info_line) {
}
bool BasicSourceLineResolver::Module::ParseCFIFrameInfo(
- char *stack_info_line) {
- char *cursor;
+ char* stack_info_line) {
+ char* cursor;
// Is this an INIT record or a delta record?
- char *init_or_address = strtok_r(stack_info_line, " \r\n", &cursor);
+ char* init_or_address = strtok_r(stack_info_line, " \r\n", &cursor);
if (!init_or_address)
return false;
if (strcmp(init_or_address, "INIT") == 0) {
// This record has the form "STACK INIT <address> <size> <rules...>".
- char *address_field = strtok_r(NULL, " \r\n", &cursor);
+ char* address_field = strtok_r(NULL, " \r\n", &cursor);
if (!address_field) return false;
- char *size_field = strtok_r(NULL, " \r\n", &cursor);
+ char* size_field = strtok_r(NULL, " \r\n", &cursor);
if (!size_field) return false;
- char *initial_rules = strtok_r(NULL, "\r\n", &cursor);
+ char* initial_rules = strtok_r(NULL, "\r\n", &cursor);
if (!initial_rules) return false;
MemAddr address = strtoul(address_field, NULL, 16);
@@ -494,17 +610,30 @@ bool BasicSourceLineResolver::Module::ParseCFIFrameInfo(
}
// This record has the form "STACK <address> <rules...>".
- char *address_field = init_or_address;
- char *delta_rules = strtok_r(NULL, "\r\n", &cursor);
+ char* address_field = init_or_address;
+ char* delta_rules = strtok_r(NULL, "\r\n", &cursor);
if (!delta_rules) return false;
MemAddr address = strtoul(address_field, NULL, 16);
cfi_delta_rules_[address] = delta_rules;
return true;
}
+bool BasicSourceLineResolver::Function::AppendInline(linked_ptr<Inline> in) {
+ // This happends if in's parent wasn't added due to a malformed INLINE record.
+ if (in->inline_nest_level > last_added_inline_nest_level + 1)
+ return false;
+
+ last_added_inline_nest_level = in->inline_nest_level;
+
+ // Store all ranges into current level of inlines.
+ for (auto range : in->inline_ranges)
+ inlines.StoreRange(range.first, range.second, in);
+ return true;
+}
+
// static
-bool SymbolParseHelper::ParseFile(char *file_line, long *index,
- char **filename) {
+bool SymbolParseHelper::ParseFile(char* file_line, long* index,
+ char** filename) {
// FILE <id> <filename>
assert(strncmp(file_line, "FILE ", 5) == 0);
file_line += 5; // skip prefix
@@ -514,7 +643,7 @@ bool SymbolParseHelper::ParseFile(char *file_line, long *index,
return false;
}
- char *after_number;
+ char* after_number;
*index = strtol(tokens[0], &after_number, 10);
if (!IsValidAfterNumber(after_number) || *index < 0 ||
*index == std::numeric_limits<long>::max()) {
@@ -530,9 +659,149 @@ bool SymbolParseHelper::ParseFile(char *file_line, long *index,
}
// static
-bool SymbolParseHelper::ParseFunction(char *function_line, bool *is_multiple,
- uint64_t *address, uint64_t *size,
- long *stack_param_size, char **name) {
+bool SymbolParseHelper::ParseInlineOrigin(char* inline_origin_line,
+ bool* has_file_id,
+ long* origin_id,
+ long* file_id,
+ char** name) {
+ // Old INLINE_ORIGIN format:
+ // INLINE_ORIGIN <origin_id> <file_id> <name>
+ // New INLINE_ORIGIN format:
+ // INLINE_ORIGIN <origin_id> <name>
+ assert(strncmp(inline_origin_line, "INLINE_ORIGIN ", 14) == 0);
+ inline_origin_line += 14; // skip prefix
+ vector<char*> tokens;
+ // Split the line into two parts so that the first token is "<origin_id>", and
+ // second token is either "<file_id> <name>"" or "<name>"" depending on the
+ // format version.
+ if (!Tokenize(inline_origin_line, kWhitespace, 2, &tokens)) {
+ return false;
+ }
+
+ char* after_number;
+ *origin_id = strtol(tokens[0], &after_number, 10);
+ if (!IsValidAfterNumber(after_number) || *origin_id < 0 ||
+ *origin_id == std::numeric_limits<long>::max()) {
+ return false;
+ }
+
+ // If the field after origin_id is a number, then it's old format.
+ char* remaining_line = tokens[1];
+ *has_file_id = true;
+ for (size_t i = 0;
+ i < strlen(remaining_line) && remaining_line[i] != ' ' && *has_file_id;
+ ++i) {
+ // If the file id is -1, it might be an artificial function that doesn't
+ // have file id. So, we consider -1 as a valid special case.
+ if (remaining_line[i] == '-' && i == 0) {
+ continue;
+ }
+ *has_file_id = isdigit(remaining_line[i]);
+ }
+
+ if (*has_file_id) {
+ // If it's old format, split "<file_id> <name>" to {"<field_id>", "<name>"}.
+ if (!Tokenize(remaining_line, kWhitespace, 2, &tokens)) {
+ return false;
+ }
+ *file_id = strtol(tokens[0], &after_number, 10);
+ // If the file id is -1, it might be an artificial function that doesn't
+ // have file id. So, we consider -1 as a valid special case.
+ if (!IsValidAfterNumber(after_number) || *file_id < -1 ||
+ *file_id == std::numeric_limits<long>::max()) {
+ return false;
+ }
+ }
+
+ *name = tokens[1];
+ if (!*name) {
+ return false;
+ }
+
+ return true;
+}
+
+// static
+bool SymbolParseHelper::ParseInline(
+ char* inline_line,
+ bool* has_call_site_file_id,
+ long* inline_nest_level,
+ long* call_site_line,
+ long* call_site_file_id,
+ long* origin_id,
+ vector<std::pair<MemAddr, MemAddr>>* ranges) {
+ // Old INLINE format:
+ // INLINE <inline_nest_level> <call_site_line> <origin_id> [<address> <size>]+
+ // New INLINE format:
+ // INLINE <inline_nest_level> <call_site_line> <call_site_file_id> <origin_id>
+ // [<address> <size>]+
+ assert(strncmp(inline_line, "INLINE ", 7) == 0);
+ inline_line += 7; // skip prefix
+
+ vector<char*> tokens;
+ // Increase max_tokens if necessary.
+ Tokenize(inline_line, kWhitespace, 512, &tokens);
+
+ // Determine the version of INLINE record by parity of the vector length.
+ *has_call_site_file_id = tokens.size() % 2 == 0;
+
+ // The length of the vector should be at least 5.
+ if (tokens.size() < 5) {
+ return false;
+ }
+
+ char* after_number;
+ size_t next_idx = 0;
+
+ *inline_nest_level = strtol(tokens[next_idx++], &after_number, 10);
+ if (!IsValidAfterNumber(after_number) || *inline_nest_level < 0 ||
+ *inline_nest_level == std::numeric_limits<long>::max()) {
+ return false;
+ }
+
+ *call_site_line = strtol(tokens[next_idx++], &after_number, 10);
+ if (!IsValidAfterNumber(after_number) || *call_site_line < 0 ||
+ *call_site_line == std::numeric_limits<long>::max()) {
+ return false;
+ }
+
+ if (*has_call_site_file_id) {
+ *call_site_file_id = strtol(tokens[next_idx++], &after_number, 10);
+ // If the file id is -1, it might be an artificial function that doesn't
+ // have file id. So, we consider -1 as a valid special case.
+ if (!IsValidAfterNumber(after_number) || *call_site_file_id < -1 ||
+ *call_site_file_id == std::numeric_limits<long>::max()) {
+ return false;
+ }
+ }
+
+ *origin_id = strtol(tokens[next_idx++], &after_number, 10);
+ if (!IsValidAfterNumber(after_number) || *origin_id < 0 ||
+ *origin_id == std::numeric_limits<long>::max()) {
+ return false;
+ }
+
+ while (next_idx < tokens.size()) {
+ MemAddr address = strtoull(tokens[next_idx++], &after_number, 16);
+ if (!IsValidAfterNumber(after_number) ||
+ address == std::numeric_limits<unsigned long long>::max()) {
+ return false;
+ }
+ MemAddr size = strtoull(tokens[next_idx++], &after_number, 16);
+ if (!IsValidAfterNumber(after_number) ||
+ size == std::numeric_limits<unsigned long long>::max()) {
+ return false;
+ }
+ ranges->push_back({address, size});
+ }
+
+ return true;
+}
+
+// static
+bool SymbolParseHelper::ParseFunction(char* function_line, bool* is_multiple,
+ uint64_t* address, uint64_t* size,
+ long* stack_param_size, char** name) {
// FUNC [<multiple>] <address> <size> <stack_param_size> <name>
assert(strncmp(function_line, "FUNC ", 5) == 0);
function_line += 5; // skip prefix
@@ -545,7 +814,7 @@ bool SymbolParseHelper::ParseFunction(char *function_line, bool *is_multiple,
*is_multiple = strcmp(tokens[0], "m") == 0;
int next_token = *is_multiple ? 1 : 0;
- char *after_number;
+ char* after_number;
*address = strtoull(tokens[next_token++], &after_number, 16);
if (!IsValidAfterNumber(after_number) ||
*address == std::numeric_limits<unsigned long long>::max()) {
@@ -568,16 +837,16 @@ bool SymbolParseHelper::ParseFunction(char *function_line, bool *is_multiple,
}
// static
-bool SymbolParseHelper::ParseLine(char *line_line, uint64_t *address,
- uint64_t *size, long *line_number,
- long *source_file) {
+bool SymbolParseHelper::ParseLine(char* line_line, uint64_t* address,
+ uint64_t* size, long* line_number,
+ long* source_file) {
// <address> <size> <line number> <source file id>
vector<char*> tokens;
if (!Tokenize(line_line, kWhitespace, 4, &tokens)) {
return false;
}
- char *after_number;
+ char* after_number;
*address = strtoull(tokens[0], &after_number, 16);
if (!IsValidAfterNumber(after_number) ||
*address == std::numeric_limits<unsigned long long>::max()) {
@@ -613,10 +882,10 @@ bool SymbolParseHelper::ParseLine(char *line_line, uint64_t *address,
}
// static
-bool SymbolParseHelper::ParsePublicSymbol(char *public_line, bool *is_multiple,
- uint64_t *address,
- long *stack_param_size,
- char **name) {
+bool SymbolParseHelper::ParsePublicSymbol(char* public_line, bool* is_multiple,
+ uint64_t* address,
+ long* stack_param_size,
+ char** name) {
// PUBLIC [<multiple>] <address> <stack_param_size> <name>
assert(strncmp(public_line, "PUBLIC ", 7) == 0);
public_line += 7; // skip prefix
@@ -629,7 +898,7 @@ bool SymbolParseHelper::ParsePublicSymbol(char *public_line, bool *is_multiple,
*is_multiple = strcmp(tokens[0], "m") == 0;
int next_token = *is_multiple ? 1 : 0;
- char *after_number;
+ char* after_number;
*address = strtoull(tokens[next_token++], &after_number, 16);
if (!IsValidAfterNumber(after_number) ||
*address == std::numeric_limits<unsigned long long>::max()) {
@@ -647,7 +916,7 @@ bool SymbolParseHelper::ParsePublicSymbol(char *public_line, bool *is_multiple,
}
// static
-bool SymbolParseHelper::IsValidAfterNumber(char *after_number) {
+bool SymbolParseHelper::IsValidAfterNumber(char* after_number) {
if (after_number != NULL && strchr(kWhitespace, *after_number) != NULL) {
return true;
}