forked from OSchip/llvm-project
[compiler-rt] Symbolizer refactoring: Abstract SymbolizerProcess better
Reviewed at http://reviews.llvm.org/D7889 llvm-svn: 230749
This commit is contained in:
parent
344c167436
commit
1cd77d4f13
|
@ -141,8 +141,8 @@ class ExternalSymbolizerInterface {
|
|||
public:
|
||||
// Can't declare pure virtual functions in sanitizer runtimes:
|
||||
// __cxa_pure_virtual might be unavailable.
|
||||
virtual char *SendCommand(bool is_data, const char *module_name,
|
||||
uptr module_offset) {
|
||||
virtual const char *SendCommand(bool is_data, const char *module_name,
|
||||
uptr module_offset) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
};
|
||||
|
@ -150,26 +150,18 @@ class ExternalSymbolizerInterface {
|
|||
// SymbolizerProcess encapsulates communication between the tool and
|
||||
// external symbolizer program, running in a different subprocess.
|
||||
// SymbolizerProcess may not be used from two threads simultaneously.
|
||||
class SymbolizerProcess : public ExternalSymbolizerInterface {
|
||||
class SymbolizerProcess {
|
||||
public:
|
||||
explicit SymbolizerProcess(const char *path);
|
||||
char *SendCommand(bool is_data, const char *module_name,
|
||||
uptr module_offset) override;
|
||||
const char *SendCommand(const char *command);
|
||||
|
||||
private:
|
||||
bool Restart();
|
||||
char *SendCommandImpl(bool is_data, const char *module_name,
|
||||
uptr module_offset);
|
||||
const char *SendCommandImpl(const char *command);
|
||||
bool ReadFromSymbolizer(char *buffer, uptr max_length);
|
||||
bool WriteToSymbolizer(const char *buffer, uptr length);
|
||||
bool StartSymbolizerSubprocess();
|
||||
|
||||
virtual bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
|
||||
const char *module_name,
|
||||
uptr module_offset) const {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
|
|
@ -105,11 +105,10 @@ SymbolizerProcess::SymbolizerProcess(const char *path)
|
|||
CHECK_NE(path_[0], '\0');
|
||||
}
|
||||
|
||||
char *SymbolizerProcess::SendCommand(bool is_data, const char *module_name,
|
||||
uptr module_offset) {
|
||||
const char *SymbolizerProcess::SendCommand(const char *command) {
|
||||
for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) {
|
||||
// Start or restart symbolizer if we failed to send command to it.
|
||||
if (char *res = SendCommandImpl(is_data, module_name, module_offset))
|
||||
if (const char *res = SendCommandImpl(command))
|
||||
return res;
|
||||
Restart();
|
||||
}
|
||||
|
@ -128,15 +127,10 @@ bool SymbolizerProcess::Restart() {
|
|||
return StartSymbolizerSubprocess();
|
||||
}
|
||||
|
||||
char *SymbolizerProcess::SendCommandImpl(bool is_data, const char *module_name,
|
||||
uptr module_offset) {
|
||||
const char *SymbolizerProcess::SendCommandImpl(const char *command) {
|
||||
if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
|
||||
return 0;
|
||||
CHECK(module_name);
|
||||
if (!RenderInputCommand(buffer_, kBufferSize, is_data, module_name,
|
||||
module_offset))
|
||||
return 0;
|
||||
if (!WriteToSymbolizer(buffer_, internal_strlen(buffer_)))
|
||||
if (!WriteToSymbolizer(command, internal_strlen(command)))
|
||||
return 0;
|
||||
if (!ReadFromSymbolizer(buffer_, kBufferSize))
|
||||
return 0;
|
||||
|
@ -343,13 +337,6 @@ class LLVMSymbolizerProcess : public SymbolizerProcess {
|
|||
explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}
|
||||
|
||||
private:
|
||||
bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
|
||||
const char *module_name, uptr module_offset) const {
|
||||
internal_snprintf(buffer, max_length, "%s\"%s\" 0x%zx\n",
|
||||
is_data ? "DATA " : "", module_name, module_offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReachedEndOfOutput(const char *buffer, uptr length) const {
|
||||
// Empty line marks the end of llvm-symbolizer output.
|
||||
return length >= 2 && buffer[length - 1] == '\n' &&
|
||||
|
@ -377,6 +364,25 @@ class LLVMSymbolizerProcess : public SymbolizerProcess {
|
|||
}
|
||||
};
|
||||
|
||||
class LLVMSymbolizer : public ExternalSymbolizerInterface {
|
||||
public:
|
||||
explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator)
|
||||
: symbolizer_process_(new(*allocator) LLVMSymbolizerProcess(path)) {}
|
||||
|
||||
const char *SendCommand(bool is_data, const char *module_name,
|
||||
uptr module_offset) override {
|
||||
CHECK(module_name);
|
||||
internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",
|
||||
is_data ? "DATA " : "", module_name, module_offset);
|
||||
return symbolizer_process_->SendCommand(buffer_);
|
||||
}
|
||||
|
||||
private:
|
||||
LLVMSymbolizerProcess *symbolizer_process_;
|
||||
static const uptr kBufferSize = 16 * 1024;
|
||||
char buffer_[kBufferSize];
|
||||
};
|
||||
|
||||
class Addr2LineProcess : public SymbolizerProcess {
|
||||
public:
|
||||
Addr2LineProcess(const char *path, const char *module_name)
|
||||
|
@ -385,15 +391,6 @@ class Addr2LineProcess : public SymbolizerProcess {
|
|||
const char *module_name() const { return module_name_; }
|
||||
|
||||
private:
|
||||
bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
|
||||
const char *module_name, uptr module_offset) const {
|
||||
if (is_data)
|
||||
return false;
|
||||
CHECK_EQ(0, internal_strcmp(module_name, module_name_));
|
||||
internal_snprintf(buffer, max_length, "0x%zx\n", module_offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReachedEndOfOutput(const char *buffer, uptr length) const {
|
||||
// Output should consist of two lines.
|
||||
int num_lines = 0;
|
||||
|
@ -420,7 +417,8 @@ class Addr2LinePool : public ExternalSymbolizerInterface {
|
|||
: addr2line_path_(addr2line_path), allocator_(allocator),
|
||||
addr2line_pool_(16) {}
|
||||
|
||||
char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
|
||||
const char *SendCommand(bool is_data, const char *module_name,
|
||||
uptr module_offset) override {
|
||||
if (is_data)
|
||||
return 0;
|
||||
Addr2LineProcess *addr2line = 0;
|
||||
|
@ -436,10 +434,14 @@ class Addr2LinePool : public ExternalSymbolizerInterface {
|
|||
new(*allocator_) Addr2LineProcess(addr2line_path_, module_name);
|
||||
addr2line_pool_.push_back(addr2line);
|
||||
}
|
||||
return addr2line->SendCommand(is_data, module_name, module_offset);
|
||||
CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
|
||||
char buffer_[kBufferSize];
|
||||
internal_snprintf(buffer_, kBufferSize, "0x%zx\n", module_offset);
|
||||
return addr2line->SendCommand(buffer_);
|
||||
}
|
||||
|
||||
private:
|
||||
static const uptr kBufferSize = 32;
|
||||
const char *addr2line_path_;
|
||||
LowLevelAllocator *allocator_;
|
||||
InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
|
||||
|
@ -628,7 +630,8 @@ class POSIXSymbolizer : public Symbolizer {
|
|||
}
|
||||
|
||||
private:
|
||||
char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
|
||||
const char *SendCommand(bool is_data, const char *module_name,
|
||||
uptr module_offset) {
|
||||
mu_.CheckLocked();
|
||||
// First, try to use internal symbolizer.
|
||||
if (internal_symbolizer_) {
|
||||
|
@ -721,7 +724,7 @@ Symbolizer *Symbolizer::PlatformInit() {
|
|||
path_to_external = FindPathToBinary("llvm-symbolizer");
|
||||
if (path_to_external) {
|
||||
external_symbolizer = new(symbolizer_allocator_)
|
||||
LLVMSymbolizerProcess(path_to_external);
|
||||
LLVMSymbolizer(path_to_external, &symbolizer_allocator_);
|
||||
} else if (common_flags()->allow_addr2line) {
|
||||
// If llvm-symbolizer is not found, try to use addr2line.
|
||||
if (const char *addr2line_path = FindPathToBinary("addr2line")) {
|
||||
|
|
Loading…
Reference in New Issue