[vm/aot] Expose static symbols in directly-generated ELF snapshots.
Also use the function labels for Dwarf in Assembly snapshots to avoid creating duplicate labels. Fixes https://github.com/dart-lang/sdk/issues/38978 Issue https://github.com/dart-lang/sdk/issues/38526 Change-Id: Icafd3d3a86381990ec8097397a21b16ad4a7a766 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122150 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Samir Jindel <sjindel@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
165196dbc0
commit
36cd2e22d4
@@ -135,10 +135,11 @@ static const intptr_t PF_W = 2;
|
||||
static const intptr_t PF_R = 4;
|
||||
|
||||
static const intptr_t SHT_PROGBITS = 1;
|
||||
static const intptr_t SHT_SYMTAB = 2;
|
||||
static const intptr_t SHT_STRTAB = 3;
|
||||
static const intptr_t SHT_HASH = 5;
|
||||
static const intptr_t SHT_DYNSYM = 11;
|
||||
static const intptr_t SHT_DYNAMIC = 6;
|
||||
static const intptr_t SHT_DYNSYM = 11;
|
||||
|
||||
static const intptr_t SHF_WRITE = 0x1;
|
||||
static const intptr_t SHF_ALLOC = 0x2;
|
||||
|
||||
+41
-24
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "vm/code_descriptors.h"
|
||||
#include "vm/elf.h"
|
||||
#include "vm/image_snapshot.h"
|
||||
#include "vm/object_store.h"
|
||||
|
||||
namespace dart {
|
||||
@@ -254,6 +255,8 @@ void Dwarf::WriteCompilationUnit() {
|
||||
uint8_t* buffer = nullptr;
|
||||
WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
|
||||
|
||||
AssemblyCodeNamer namer(zone_);
|
||||
|
||||
if (asm_stream_) {
|
||||
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
|
||||
Print(".section __DWARF,__debug_info,regular,debug\n");
|
||||
@@ -314,8 +317,8 @@ void Dwarf::WriteCompilationUnit() {
|
||||
if (asm_stream_) {
|
||||
intptr_t last_code_index = codes_.length() - 1;
|
||||
const Code& last_code = *(codes_[last_code_index]);
|
||||
Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", last_code_index,
|
||||
last_code.Size());
|
||||
Print(FORM_ADDR " %s + %" Pd "\n",
|
||||
namer.AssemblyNameFor(last_code_index, last_code), last_code.Size());
|
||||
} else {
|
||||
addr(elf_->NextMemoryOffset());
|
||||
}
|
||||
@@ -373,6 +376,7 @@ void Dwarf::WriteAbstractFunctions() {
|
||||
void Dwarf::WriteConcreteFunctions() {
|
||||
Function& function = Function::Handle(zone_);
|
||||
Script& script = Script::Handle(zone_);
|
||||
AssemblyCodeNamer namer(zone_);
|
||||
for (intptr_t i = 0; i < codes_.length(); i++) {
|
||||
const Code& code = *(codes_[i]);
|
||||
RELEASE_ASSERT(!code.IsNull());
|
||||
@@ -403,14 +407,13 @@ void Dwarf::WriteConcreteFunctions() {
|
||||
|
||||
// DW_AT_low_pc
|
||||
if (asm_stream_) {
|
||||
Print(FORM_ADDR " .Lcode%" Pd "\n", i);
|
||||
const char* asm_name = namer.AssemblyNameFor(i, code);
|
||||
// DW_AT_low_pc
|
||||
Print(FORM_ADDR " %s\n", asm_name);
|
||||
// DW_AT_high_pc
|
||||
Print(FORM_ADDR " %s + %" Pd "\n", asm_name, code.Size());
|
||||
} else {
|
||||
addr(code_offset);
|
||||
}
|
||||
// DW_AT_high_pc
|
||||
if (asm_stream_) {
|
||||
Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", i, code.Size());
|
||||
} else {
|
||||
addr(code_offset + code.Size());
|
||||
}
|
||||
|
||||
@@ -418,7 +421,7 @@ void Dwarf::WriteConcreteFunctions() {
|
||||
if (node != NULL) {
|
||||
for (InliningNode* child = node->children_head; child != NULL;
|
||||
child = child->children_next) {
|
||||
WriteInliningNode(child, i, script);
|
||||
WriteInliningNode(child, i, script, &namer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -509,7 +512,8 @@ InliningNode* Dwarf::ExpandInliningTree(const Code& code) {
|
||||
|
||||
void Dwarf::WriteInliningNode(InliningNode* node,
|
||||
intptr_t root_code_index,
|
||||
const Script& parent_script) {
|
||||
const Script& parent_script,
|
||||
AssemblyCodeNamer* namer) {
|
||||
intptr_t file = LookupScript(parent_script);
|
||||
intptr_t line = node->call_pos.value();
|
||||
intptr_t function_index = LookupFunction(node->function);
|
||||
@@ -527,20 +531,21 @@ void Dwarf::WriteInliningNode(InliningNode* node,
|
||||
} else {
|
||||
u4(abstract_origins_[function_index]);
|
||||
}
|
||||
// DW_AT_low_pc
|
||||
|
||||
if (asm_stream_) {
|
||||
Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
|
||||
node->start_pc_offset);
|
||||
const char* asm_name =
|
||||
namer->AssemblyNameFor(root_code_index, *codes_[root_code_index]);
|
||||
// DW_AT_low_pc
|
||||
Print(FORM_ADDR " %s + %d\n", asm_name, node->start_pc_offset);
|
||||
// DW_AT_high_pc
|
||||
Print(FORM_ADDR " %s + %d\n", asm_name, node->end_pc_offset);
|
||||
} else {
|
||||
// DW_AT_low_pc
|
||||
addr(root_code_index + node->start_pc_offset);
|
||||
}
|
||||
// DW_AT_high_pc
|
||||
if (asm_stream_) {
|
||||
Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
|
||||
node->end_pc_offset);
|
||||
} else {
|
||||
addr(root_code_index + node->end_pc_offset);
|
||||
}
|
||||
|
||||
// DW_AT_call_file
|
||||
uleb128(file);
|
||||
// DW_AT_call_line
|
||||
@@ -548,7 +553,7 @@ void Dwarf::WriteInliningNode(InliningNode* node,
|
||||
|
||||
for (InliningNode* child = node->children_head; child != NULL;
|
||||
child = child->children_next) {
|
||||
WriteInliningNode(child, root_code_index, script);
|
||||
WriteInliningNode(child, root_code_index, script, namer);
|
||||
}
|
||||
|
||||
uleb128(0); // End of children.
|
||||
@@ -655,10 +660,16 @@ void Dwarf::WriteLines() {
|
||||
Array& functions = Array::Handle(zone_);
|
||||
GrowableArray<const Function*> function_stack(zone_, 8);
|
||||
GrowableArray<TokenPosition> token_positions(zone_, 8);
|
||||
AssemblyCodeNamer namer(zone_);
|
||||
|
||||
for (intptr_t i = 0; i < codes_.length(); i++) {
|
||||
const Code& code = *(codes_[i]);
|
||||
|
||||
const char* asm_name = nullptr;
|
||||
if (asm_stream_ != nullptr) {
|
||||
asm_name = namer.AssemblyNameFor(i, code);
|
||||
}
|
||||
|
||||
CodeIndexPair* pair = code_to_index_.Lookup(&code);
|
||||
RELEASE_ASSERT(pair != NULL);
|
||||
intptr_t current_code_offset = pair->index_;
|
||||
@@ -723,15 +734,16 @@ void Dwarf::WriteLines() {
|
||||
u1(1 + sizeof(void*)); // that is 5 or 9 bytes long
|
||||
u1(DW_LNE_set_address);
|
||||
if (asm_stream_) {
|
||||
Print(FORM_ADDR " .Lcode%" Pd " + %d\n", i, current_pc_offset);
|
||||
Print(FORM_ADDR " %s + %d\n", asm_name, current_pc_offset);
|
||||
} else {
|
||||
addr(current_code_offset + current_pc_offset);
|
||||
}
|
||||
} else {
|
||||
u1(DW_LNS_advance_pc);
|
||||
if (asm_stream_) {
|
||||
Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", i,
|
||||
previous_code_offset,
|
||||
const char* previous_asm_name = namer.AssemblyNameFor(
|
||||
previous_code_offset, *codes_[previous_code_offset]);
|
||||
Print(".uleb128 %s - %s + %" Pd "\n", asm_name, previous_asm_name,
|
||||
current_pc_offset - previous_pc_offset);
|
||||
} else {
|
||||
intptr_t delta = current_code_offset - previous_code_offset +
|
||||
@@ -780,8 +792,13 @@ void Dwarf::WriteLines() {
|
||||
|
||||
u1(DW_LNS_advance_pc);
|
||||
if (asm_stream_) {
|
||||
Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", last_code_index,
|
||||
previous_code_offset, last_code.Size() - previous_pc_offset);
|
||||
const char* last_asm_name =
|
||||
namer.AssemblyNameFor(last_code_index, last_code);
|
||||
ASSERT(previous_code_offset >= 0);
|
||||
const char* previous_asm_name = namer.AssemblyNameFor(
|
||||
previous_code_offset, *codes_[previous_code_offset]);
|
||||
Print(".uleb128 %s - %s + %" Pd "\n", last_asm_name, previous_asm_name,
|
||||
last_code.Size() - previous_pc_offset);
|
||||
} else {
|
||||
intptr_t delta = last_code_offset - previous_code_offset +
|
||||
last_code.Size() - previous_pc_offset;
|
||||
|
||||
+3
-1
@@ -16,6 +16,7 @@ namespace dart {
|
||||
|
||||
class Elf;
|
||||
class InliningNode;
|
||||
class AssemblyCodeNamer;
|
||||
|
||||
struct ScriptIndexPair {
|
||||
// Typedefs needed for the DirectChainedHashMap template.
|
||||
@@ -285,7 +286,8 @@ class Dwarf : public ZoneAllocated {
|
||||
InliningNode* ExpandInliningTree(const Code& code);
|
||||
void WriteInliningNode(InliningNode* node,
|
||||
intptr_t root_code_index,
|
||||
const Script& parent_script);
|
||||
const Script& parent_script,
|
||||
AssemblyCodeNamer* namer);
|
||||
void WriteLines();
|
||||
|
||||
Zone* const zone_;
|
||||
|
||||
+59
-23
@@ -132,11 +132,19 @@ class Symbol : public ZoneAllocated {
|
||||
|
||||
class SymbolTable : public Section {
|
||||
public:
|
||||
SymbolTable() {
|
||||
section_type = elf::SHT_DYNSYM;
|
||||
section_flags = elf::SHF_ALLOC;
|
||||
segment_type = elf::PT_LOAD;
|
||||
segment_flags = elf::PF_R;
|
||||
explicit SymbolTable(bool dynamic) {
|
||||
if (dynamic) {
|
||||
section_type = elf::SHT_DYNSYM;
|
||||
section_flags = elf::SHF_ALLOC;
|
||||
segment_type = elf::PT_LOAD;
|
||||
segment_flags = elf::PF_R;
|
||||
} else {
|
||||
// No need to load the static symbol table at runtime since it's ignored
|
||||
// by the dynamic linker.
|
||||
section_type = elf::SHT_SYMTAB;
|
||||
memory_offset = 0;
|
||||
section_flags = 0;
|
||||
}
|
||||
|
||||
section_entry_size = kElfSymbolTableEntrySize;
|
||||
AddSymbol(NULL);
|
||||
@@ -339,11 +347,17 @@ Elf::Elf(Zone* zone, StreamingWriteStream* stream)
|
||||
shstrtab_ = new (zone_) StringTable(/* allocate= */ false);
|
||||
shstrtab_->section_name = shstrtab_->AddString(".shstrtab");
|
||||
|
||||
symstrtab_ = new (zone_) StringTable(/* allocate= */ true);
|
||||
symstrtab_->section_name = shstrtab_->AddString(".dynstr");
|
||||
dynstrtab_ = new (zone_) StringTable(/* allocate= */ true);
|
||||
dynstrtab_->section_name = shstrtab_->AddString(".dynstr");
|
||||
|
||||
symtab_ = new (zone_) SymbolTable();
|
||||
symtab_->section_name = shstrtab_->AddString(".dynsym");
|
||||
dynsym_ = new (zone_) SymbolTable(/*dynamic=*/true);
|
||||
dynsym_->section_name = shstrtab_->AddString(".dynsym");
|
||||
|
||||
strtab_ = new (zone_) StringTable(/* allocate= */ false);
|
||||
strtab_->section_name = shstrtab_->AddString(".strtab");
|
||||
|
||||
symtab_ = new (zone_) SymbolTable(/*dynamic=*/false);
|
||||
symtab_->section_name = shstrtab_->AddString(".symtab");
|
||||
|
||||
// Allocate regular segments after the program table.
|
||||
memory_offset_ = kProgramTableSegmentSize;
|
||||
@@ -366,10 +380,14 @@ void Elf::AddSegment(Section* section) {
|
||||
memory_offset_ = Utils::RoundUp(memory_offset_, kPageSize);
|
||||
}
|
||||
|
||||
intptr_t Elf::NextMemoryOffset() {
|
||||
intptr_t Elf::NextMemoryOffset() const {
|
||||
return memory_offset_;
|
||||
}
|
||||
|
||||
intptr_t Elf::NextSectionIndex() const {
|
||||
return sections_.length() + kNumInvalidSections;
|
||||
}
|
||||
|
||||
intptr_t Elf::AddText(const char* name, const uint8_t* bytes, intptr_t size) {
|
||||
ProgramBits* image = new (zone_) ProgramBits(true, true, false, bytes, size);
|
||||
image->section_name = shstrtab_->AddString(".text");
|
||||
@@ -378,18 +396,33 @@ intptr_t Elf::AddText(const char* name, const uint8_t* bytes, intptr_t size) {
|
||||
|
||||
Symbol* symbol = new (zone_) Symbol();
|
||||
symbol->cstr = name;
|
||||
symbol->name = symstrtab_->AddString(name);
|
||||
symbol->name = dynstrtab_->AddString(name);
|
||||
symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_FUNC;
|
||||
symbol->section = image->section_index;
|
||||
// For shared libraries, this is the offset from the DSO base. For static
|
||||
// libraries, this is section relative.
|
||||
symbol->offset = image->memory_offset;
|
||||
symbol->size = size;
|
||||
symtab_->AddSymbol(symbol);
|
||||
dynsym_->AddSymbol(symbol);
|
||||
|
||||
return symbol->offset;
|
||||
}
|
||||
|
||||
void Elf::AddStaticSymbol(intptr_t section,
|
||||
const char* name,
|
||||
size_t memory_offset) {
|
||||
Symbol* symbol = new (zone_) Symbol();
|
||||
symbol->cstr = name;
|
||||
symbol->name = strtab_->AddString(name);
|
||||
symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_FUNC;
|
||||
symbol->section = section;
|
||||
// For shared libraries, this is the offset from the DSO base. For static
|
||||
// libraries, this is section relative.
|
||||
symbol->offset = memory_offset;
|
||||
symbol->size = 0;
|
||||
symtab_->AddSymbol(symbol);
|
||||
}
|
||||
|
||||
intptr_t Elf::AddBSSData(const char* name, intptr_t size) {
|
||||
// Ideally the BSS segment would take no space in the object, but Android's
|
||||
// "strip" utility truncates the memory-size of our segments to their
|
||||
@@ -407,14 +440,14 @@ intptr_t Elf::AddBSSData(const char* name, intptr_t size) {
|
||||
|
||||
Symbol* symbol = new (zone_) Symbol();
|
||||
symbol->cstr = name;
|
||||
symbol->name = symstrtab_->AddString(name);
|
||||
symbol->name = dynstrtab_->AddString(name);
|
||||
symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_OBJECT;
|
||||
symbol->section = image->section_index;
|
||||
// For shared libraries, this is the offset from the DSO base. For static
|
||||
// libraries, this is section relative.
|
||||
symbol->offset = image->memory_offset;
|
||||
symbol->size = size;
|
||||
symtab_->AddSymbol(symbol);
|
||||
dynsym_->AddSymbol(symbol);
|
||||
|
||||
return symbol->offset;
|
||||
}
|
||||
@@ -427,14 +460,14 @@ intptr_t Elf::AddROData(const char* name, const uint8_t* bytes, intptr_t size) {
|
||||
|
||||
Symbol* symbol = new (zone_) Symbol();
|
||||
symbol->cstr = name;
|
||||
symbol->name = symstrtab_->AddString(name);
|
||||
symbol->name = dynstrtab_->AddString(name);
|
||||
symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_OBJECT;
|
||||
symbol->section = image->section_index;
|
||||
// For shared libraries, this is the offset from the DSO base. For static
|
||||
// libraries, this is section relative.
|
||||
symbol->offset = image->memory_offset;
|
||||
symbol->size = size;
|
||||
symtab_->AddSymbol(symbol);
|
||||
dynsym_->AddSymbol(symbol);
|
||||
|
||||
return symbol->offset;
|
||||
}
|
||||
@@ -447,25 +480,28 @@ void Elf::AddDebug(const char* name, const uint8_t* bytes, intptr_t size) {
|
||||
}
|
||||
|
||||
void Elf::Finalize() {
|
||||
SymbolHashTable* hash = new (zone_) SymbolHashTable(symstrtab_, symtab_);
|
||||
SymbolHashTable* hash = new (zone_) SymbolHashTable(dynstrtab_, dynsym_);
|
||||
hash->section_name = shstrtab_->AddString(".hash");
|
||||
|
||||
AddSection(hash);
|
||||
AddSection(dynsym_);
|
||||
AddSection(dynstrtab_);
|
||||
AddSection(strtab_);
|
||||
AddSection(symtab_);
|
||||
AddSection(symstrtab_);
|
||||
|
||||
symtab_->section_link = symstrtab_->section_index;
|
||||
hash->section_link = symtab_->section_index;
|
||||
dynsym_->section_link = dynstrtab_->section_index;
|
||||
hash->section_link = dynsym_->section_index;
|
||||
symtab_->section_link = strtab_->section_index;
|
||||
|
||||
// Before finalizing the string table's memory size:
|
||||
intptr_t name_dynamic = shstrtab_->AddString(".dynamic");
|
||||
|
||||
// Finalizes memory size of string and symbol tables.
|
||||
AddSegment(hash);
|
||||
AddSegment(symtab_);
|
||||
AddSegment(symstrtab_);
|
||||
AddSegment(dynsym_);
|
||||
AddSegment(dynstrtab_);
|
||||
|
||||
dynamic_ = new (zone_) DynamicTable(symstrtab_, symtab_, hash);
|
||||
dynamic_ = new (zone_) DynamicTable(dynstrtab_, dynsym_, hash);
|
||||
dynamic_->section_name = name_dynamic;
|
||||
AddSection(dynamic_);
|
||||
AddSegment(dynamic_);
|
||||
|
||||
+8
-2
@@ -25,11 +25,15 @@ class Elf : public ZoneAllocated {
|
||||
|
||||
static const intptr_t kPageSize = 4096;
|
||||
|
||||
intptr_t NextMemoryOffset();
|
||||
intptr_t NextMemoryOffset() const;
|
||||
intptr_t NextSectionIndex() const;
|
||||
intptr_t AddText(const char* name, const uint8_t* bytes, intptr_t size);
|
||||
intptr_t AddROData(const char* name, const uint8_t* bytes, intptr_t size);
|
||||
intptr_t AddBSSData(const char* name, intptr_t size);
|
||||
void AddDebug(const char* name, const uint8_t* bytes, intptr_t size);
|
||||
void AddStaticSymbol(intptr_t section,
|
||||
const char* name,
|
||||
size_t memory_offset);
|
||||
|
||||
void Finalize();
|
||||
|
||||
@@ -79,7 +83,9 @@ class Elf : public ZoneAllocated {
|
||||
intptr_t program_table_file_offset_;
|
||||
intptr_t program_table_file_size_;
|
||||
StringTable* shstrtab_;
|
||||
StringTable* symstrtab_;
|
||||
StringTable* dynstrtab_;
|
||||
SymbolTable* dynsym_;
|
||||
StringTable* strtab_;
|
||||
SymbolTable* symtab_;
|
||||
DynamicTable* dynamic_;
|
||||
};
|
||||
|
||||
@@ -492,6 +492,40 @@ static const char* NameOfStubIsolateSpecificStub(ObjectStore* object_store,
|
||||
}
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
const char* AssemblyCodeNamer::AssemblyNameFor(intptr_t code_index,
|
||||
const Code& code) {
|
||||
ASSERT(!code.IsNull());
|
||||
owner_ = code.owner();
|
||||
if (owner_.IsNull()) {
|
||||
insns_ = code.instructions();
|
||||
const char* name = StubCode::NameOfStub(insns_.EntryPoint());
|
||||
if (name != nullptr) {
|
||||
return OS::SCreate(zone_, "Precompiled_Stub_%s", name);
|
||||
} else {
|
||||
if (name == nullptr) {
|
||||
name = NameOfStubIsolateSpecificStub(store_, code);
|
||||
}
|
||||
ASSERT(name != nullptr);
|
||||
return OS::SCreate(zone_, "Precompiled__%s", name);
|
||||
}
|
||||
} else if (owner_.IsClass()) {
|
||||
string_ = Class::Cast(owner_).Name();
|
||||
const char* name = string_.ToCString();
|
||||
EnsureAssemblerIdentifier(const_cast<char*>(name));
|
||||
return OS::SCreate(zone_, "Precompiled_AllocationStub_%s_%" Pd, name,
|
||||
code_index);
|
||||
} else if (owner_.IsAbstractType()) {
|
||||
const char* name = namer_.StubNameForType(AbstractType::Cast(owner_));
|
||||
return OS::SCreate(zone_, "Precompiled_%s", name);
|
||||
} else if (owner_.IsFunction()) {
|
||||
const char* name = Function::Cast(owner_).ToQualifiedCString();
|
||||
EnsureAssemblerIdentifier(const_cast<char*>(name));
|
||||
return OS::SCreate(zone_, "Precompiled_%s_%" Pd, name, code_index);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
UNREACHABLE();
|
||||
@@ -532,13 +566,8 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
||||
|
||||
FrameUnwindPrologue();
|
||||
|
||||
Object& owner = Object::Handle(zone);
|
||||
String& str = String::Handle(zone);
|
||||
PcDescriptors& descriptors = PcDescriptors::Handle(zone);
|
||||
|
||||
ObjectStore* object_store = Isolate::Current()->object_store();
|
||||
|
||||
TypeTestingStubNamer tts;
|
||||
AssemblyCodeNamer namer(zone);
|
||||
intptr_t text_offset = 0;
|
||||
|
||||
ASSERT(offset_space_ != V8SnapshotProfileWriter::kSnapshot);
|
||||
@@ -620,45 +649,16 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
||||
compiler::target::Instructions::HeaderSize());
|
||||
}
|
||||
|
||||
// 2. Write a label at the entry point.
|
||||
// Linux's perf uses these labels.
|
||||
ASSERT(!code.IsNull());
|
||||
owner = code.owner();
|
||||
if (owner.IsNull()) {
|
||||
const char* name = StubCode::NameOfStub(insns.EntryPoint());
|
||||
if (name != nullptr) {
|
||||
assembly_stream_.Print("Precompiled_Stub_%s:\n", name);
|
||||
} else {
|
||||
if (name == nullptr) {
|
||||
name = NameOfStubIsolateSpecificStub(object_store, code);
|
||||
}
|
||||
ASSERT(name != nullptr);
|
||||
assembly_stream_.Print("Precompiled__%s:\n", name);
|
||||
}
|
||||
} else if (owner.IsClass()) {
|
||||
str = Class::Cast(owner).Name();
|
||||
const char* name = str.ToCString();
|
||||
EnsureAssemblerIdentifier(const_cast<char*>(name));
|
||||
assembly_stream_.Print("Precompiled_AllocationStub_%s_%" Pd ":\n", name,
|
||||
i);
|
||||
} else if (owner.IsAbstractType()) {
|
||||
const char* name = tts.StubNameForType(AbstractType::Cast(owner));
|
||||
assembly_stream_.Print("Precompiled_%s:\n", name);
|
||||
} else if (owner.IsFunction()) {
|
||||
const char* name = Function::Cast(owner).ToQualifiedCString();
|
||||
EnsureAssemblerIdentifier(const_cast<char*>(name));
|
||||
assembly_stream_.Print("Precompiled_%s_%" Pd ":\n", name, i);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
intptr_t dwarf_index = i;
|
||||
#ifdef DART_PRECOMPILER
|
||||
// Create a label for use by DWARF.
|
||||
if ((dwarf_ != nullptr) && !code.IsNull()) {
|
||||
const intptr_t dwarf_index = dwarf_->AddCode(code);
|
||||
assembly_stream_.Print(".Lcode%" Pd ":\n", dwarf_index);
|
||||
dwarf_index = dwarf_->AddCode(code);
|
||||
}
|
||||
#endif
|
||||
// 2. Write a label at the entry point.
|
||||
// Linux's perf uses these labels.
|
||||
assembly_stream_.Print("%s:\n", namer.AssemblyNameFor(dwarf_index, code));
|
||||
|
||||
{
|
||||
// 3. Write from the payload start to payload end.
|
||||
@@ -888,6 +888,7 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
PcDescriptors& descriptors = PcDescriptors::Handle();
|
||||
AssemblyCodeNamer namer(Thread::Current()->zone());
|
||||
#endif
|
||||
|
||||
NoSafepointScope no_safepoint;
|
||||
@@ -973,6 +974,12 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
||||
#endif // defined(IS_SIMARM_X64)
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
if (elf_ != nullptr && dwarf_ != nullptr) {
|
||||
elf_->AddStaticSymbol(elf_->NextSectionIndex(),
|
||||
namer.AssemblyNameFor(i, code),
|
||||
segment_base + payload_stream_start);
|
||||
}
|
||||
|
||||
// Don't patch the relocation if we're not generating ELF. The regular blobs
|
||||
// format does not yet support these relocations. Use
|
||||
// Code::VerifyBSSRelocations to check whether the relocations are patched
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "vm/hash_map.h"
|
||||
#include "vm/object.h"
|
||||
#include "vm/reusable_handles.h"
|
||||
#include "vm/type_testing_stubs.h"
|
||||
#include "vm/v8_snapshot_writer.h"
|
||||
|
||||
namespace dart {
|
||||
@@ -291,6 +292,28 @@ class TraceImageObjectScope {
|
||||
intptr_t start_offset_;
|
||||
};
|
||||
|
||||
class AssemblyCodeNamer {
|
||||
public:
|
||||
explicit AssemblyCodeNamer(Zone* zone)
|
||||
: zone_(zone),
|
||||
owner_(Object::Handle(zone)),
|
||||
string_(String::Handle(zone)),
|
||||
insns_(Instructions::Handle(zone)),
|
||||
store_(Isolate::Current()->object_store()) {}
|
||||
|
||||
const char* StubNameForType(const AbstractType& type) const;
|
||||
|
||||
const char* AssemblyNameFor(intptr_t code_index, const Code& code);
|
||||
|
||||
private:
|
||||
Zone* const zone_;
|
||||
Object& owner_;
|
||||
String& string_;
|
||||
Instructions& insns_;
|
||||
ObjectStore* const store_;
|
||||
TypeTestingStubNamer namer_;
|
||||
};
|
||||
|
||||
class AssemblyImageWriter : public ImageWriter {
|
||||
public:
|
||||
AssemblyImageWriter(Thread* thread,
|
||||
|
||||
Reference in New Issue
Block a user