2017-03-20 20:02:41 +00:00
|
|
|
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
|
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "vm/dwarf.h"
|
|
|
|
|
|
|
|
#include "vm/code_descriptors.h"
|
2019-05-28 18:48:57 +00:00
|
|
|
#include "vm/elf.h"
|
2019-10-25 11:53:14 +00:00
|
|
|
#include "vm/image_snapshot.h"
|
2017-03-20 20:02:41 +00:00
|
|
|
#include "vm/object_store.h"
|
|
|
|
|
|
|
|
namespace dart {
|
|
|
|
|
2020-06-22 09:29:45 +00:00
|
|
|
#if defined(DART_PRECOMPILER)
|
|
|
|
|
|
|
|
class DwarfPosition {
|
|
|
|
public:
|
|
|
|
// The DWARF standard uses 0 to denote missing line or column information.
|
|
|
|
DwarfPosition(intptr_t line, intptr_t column)
|
|
|
|
: line_(line > 0 ? line : 0), column_(column > 0 ? column : 0) {
|
|
|
|
// Should only have no line information if also no column information.
|
|
|
|
ASSERT(line_ > 0 || column_ == 0);
|
|
|
|
}
|
|
|
|
explicit DwarfPosition(intptr_t line) : DwarfPosition(line, 0) {}
|
|
|
|
constexpr DwarfPosition() : line_(0), column_(0) {}
|
|
|
|
|
|
|
|
intptr_t line() const { return line_; }
|
|
|
|
intptr_t column() const { return column_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
intptr_t line_;
|
|
|
|
intptr_t column_;
|
|
|
|
};
|
|
|
|
|
|
|
|
static constexpr auto kNoDwarfPositionInfo = DwarfPosition();
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
class InliningNode : public ZoneAllocated {
|
|
|
|
public:
|
|
|
|
InliningNode(const Function& function,
|
2020-06-22 09:29:45 +00:00
|
|
|
const DwarfPosition& position,
|
2017-03-20 20:02:41 +00:00
|
|
|
int32_t start_pc_offset)
|
|
|
|
: function(function),
|
2020-06-22 09:29:45 +00:00
|
|
|
position(position),
|
2017-03-20 20:02:41 +00:00
|
|
|
start_pc_offset(start_pc_offset),
|
|
|
|
end_pc_offset(-1),
|
|
|
|
children_head(NULL),
|
|
|
|
children_tail(NULL),
|
2018-02-09 18:49:39 +00:00
|
|
|
children_next(NULL) {
|
2018-02-16 20:48:59 +00:00
|
|
|
RELEASE_ASSERT(!function.IsNull());
|
|
|
|
RELEASE_ASSERT(function.IsNotTemporaryScopedHandle());
|
2018-02-09 18:49:39 +00:00
|
|
|
}
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
void AppendChild(InliningNode* child) {
|
|
|
|
if (children_tail == NULL) {
|
|
|
|
children_head = children_tail = child;
|
|
|
|
} else {
|
|
|
|
children_tail->children_next = child;
|
|
|
|
children_tail = child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const Function& function;
|
2020-06-22 09:29:45 +00:00
|
|
|
DwarfPosition position;
|
2017-03-20 20:02:41 +00:00
|
|
|
int32_t start_pc_offset;
|
|
|
|
int32_t end_pc_offset;
|
|
|
|
InliningNode* children_head;
|
|
|
|
InliningNode* children_tail;
|
|
|
|
InliningNode* children_next;
|
|
|
|
};
|
|
|
|
|
2019-12-18 14:14:41 +00:00
|
|
|
template <typename T>
|
|
|
|
Trie<T>* Trie<T>::AddString(Zone* zone,
|
|
|
|
Trie<T>* trie,
|
|
|
|
const char* key,
|
|
|
|
const T* value) {
|
|
|
|
ASSERT(key != nullptr);
|
|
|
|
if (trie == nullptr) {
|
|
|
|
trie = new (zone) Trie<T>();
|
|
|
|
}
|
|
|
|
if (*key == '\0') {
|
|
|
|
ASSERT(trie->value_ == nullptr);
|
|
|
|
trie->value_ = value;
|
|
|
|
} else {
|
|
|
|
auto const index = ChildIndex(*key);
|
|
|
|
ASSERT(index >= 0 && index < kNumValidChars);
|
|
|
|
trie->children_[index] =
|
|
|
|
AddString(zone, trie->children_[index], key + 1, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return trie;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
const T* Trie<T>::Lookup(const Trie<T>* trie, const char* key, intptr_t* end) {
|
|
|
|
intptr_t i = 0;
|
|
|
|
for (; key[i] != '\0'; i++) {
|
|
|
|
auto const index = ChildIndex(key[i]);
|
|
|
|
ASSERT(index < kNumValidChars);
|
|
|
|
if (index < 0) {
|
|
|
|
if (end == nullptr) return nullptr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Still find the longest valid trie prefix when no stored value.
|
|
|
|
if (trie == nullptr) continue;
|
|
|
|
trie = trie->children_[index];
|
|
|
|
}
|
|
|
|
if (end != nullptr) {
|
|
|
|
*end = i;
|
|
|
|
}
|
|
|
|
if (trie == nullptr) return nullptr;
|
|
|
|
return trie->value_;
|
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
Dwarf::Dwarf(Zone* zone)
|
2017-03-20 20:02:41 +00:00
|
|
|
: zone_(zone),
|
2019-12-18 14:14:41 +00:00
|
|
|
reverse_obfuscation_trie_(CreateReverseObfuscationTrie(zone)),
|
2017-03-20 20:02:41 +00:00
|
|
|
codes_(zone, 1024),
|
2019-12-20 10:14:10 +00:00
|
|
|
code_to_address_(zone),
|
2017-03-20 20:02:41 +00:00
|
|
|
functions_(zone, 1024),
|
|
|
|
function_to_index_(zone),
|
|
|
|
scripts_(zone, 1024),
|
|
|
|
script_to_index_(zone),
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
temp_(0) {}
|
|
|
|
|
2020-06-12 11:34:02 +00:00
|
|
|
SegmentRelativeOffset Dwarf::CodeAddress(const Code& code) const {
|
|
|
|
const auto& pair = code_to_address_.LookupValue(&code);
|
|
|
|
// This is only used by Elf::Finalize(), and the image writers always give a
|
|
|
|
// text offset when calling AddCode() for an Elf object's Dwarf object. Thus,
|
|
|
|
// we should have known code offsets for each code object in the map.
|
|
|
|
ASSERT(pair.offset != SegmentRelativeOffset::kUnknownOffset);
|
|
|
|
return pair;
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t Dwarf::AddCode(const Code& orig_code,
|
|
|
|
const SegmentRelativeOffset& offset) {
|
|
|
|
ASSERT(!orig_code.IsNull());
|
|
|
|
// We should never get the no-argument constructed version here.
|
|
|
|
ASSERT(offset.offset != SegmentRelativeOffset::kInvalidOffset);
|
|
|
|
// Generate an appropriately zoned ZoneHandle for storing.
|
|
|
|
const auto& code = Code::ZoneHandle(zone_, orig_code.raw());
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
|
|
|
|
// For now, we assume one of two flows for a given code object:
|
2020-06-12 11:34:02 +00:00
|
|
|
// ELF: Calls to AddCode(code, vm, offset), vm and offset are the same over
|
|
|
|
// all calls.
|
|
|
|
// Assembly: An initial call to AddCode(code, vm) (assembly), possibly
|
|
|
|
// followed by a later call to AddCode(code, vm, offset)
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
// (separate debugging info ELF)
|
2020-06-12 11:34:02 +00:00
|
|
|
if (offset.offset == SegmentRelativeOffset::kUnknownOffset) {
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
// A call without an address should always come before any calls with
|
|
|
|
// addresses.
|
|
|
|
ASSERT(code_to_address_.Lookup(&code) == nullptr);
|
|
|
|
// Insert a marker so on later calls, we know we've already added to codes_.
|
2020-06-12 11:34:02 +00:00
|
|
|
code_to_address_.Insert(CodeAddressPair(&code, offset));
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
} else {
|
2020-06-12 11:34:02 +00:00
|
|
|
const auto& old_value = code_to_address_.LookupValue(&code);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
// ELF does not need to know the index. If we've already added this Code
|
|
|
|
// object to codes_ in a previous call, don't bother scanning codes_ to find
|
|
|
|
// the corresponding index, just return -1 instead.
|
2020-06-12 11:34:02 +00:00
|
|
|
switch (old_value.offset) {
|
|
|
|
case SegmentRelativeOffset::kInvalidOffset:
|
|
|
|
code_to_address_.Insert(CodeAddressPair(&code, offset));
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
break; // Still need to add to codes_.
|
2020-06-12 11:34:02 +00:00
|
|
|
case SegmentRelativeOffset::kUnknownOffset:
|
|
|
|
// Code objects should only be associated with either the VM or isolate.
|
|
|
|
ASSERT_EQUAL(old_value.vm, offset.vm);
|
|
|
|
code_to_address_.Update(CodeAddressPair(&code, offset));
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
return -1;
|
|
|
|
default:
|
2020-06-12 11:34:02 +00:00
|
|
|
// The information for the code object shouldn't have changed since the
|
|
|
|
// previous update.
|
|
|
|
ASSERT(old_value == offset);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2020-03-13 14:14:01 +00:00
|
|
|
|
2019-12-20 10:14:10 +00:00
|
|
|
const intptr_t index = codes_.length();
|
2020-03-13 14:14:01 +00:00
|
|
|
codes_.Add(&code);
|
2017-03-20 20:02:41 +00:00
|
|
|
if (code.IsFunctionCode()) {
|
|
|
|
const Function& function = Function::Handle(zone_, code.function());
|
|
|
|
AddFunction(function);
|
|
|
|
}
|
|
|
|
const Array& inline_functions =
|
|
|
|
Array::Handle(zone_, code.inlined_id_to_function());
|
|
|
|
if (!inline_functions.IsNull()) {
|
|
|
|
Function& function = Function::Handle(zone_);
|
|
|
|
for (intptr_t i = 0; i < inline_functions.Length(); i++) {
|
|
|
|
function ^= inline_functions.At(i);
|
|
|
|
AddFunction(function);
|
|
|
|
}
|
|
|
|
}
|
2019-12-20 10:14:10 +00:00
|
|
|
return index;
|
2017-03-20 20:02:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t Dwarf::AddFunction(const Function& function) {
|
2018-02-09 18:49:39 +00:00
|
|
|
RELEASE_ASSERT(!function.IsNull());
|
2017-03-20 20:02:41 +00:00
|
|
|
FunctionIndexPair* pair = function_to_index_.Lookup(&function);
|
|
|
|
if (pair != NULL) {
|
|
|
|
return pair->index_;
|
|
|
|
}
|
|
|
|
intptr_t index = functions_.length();
|
|
|
|
const Function& zone_func = Function::ZoneHandle(zone_, function.raw());
|
|
|
|
function_to_index_.Insert(FunctionIndexPair(&zone_func, index));
|
|
|
|
functions_.Add(&zone_func);
|
|
|
|
const Script& script = Script::Handle(zone_, function.script());
|
|
|
|
AddScript(script);
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t Dwarf::AddScript(const Script& script) {
|
2018-02-16 20:48:59 +00:00
|
|
|
RELEASE_ASSERT(!script.IsNull());
|
2017-03-20 20:02:41 +00:00
|
|
|
ScriptIndexPair* pair = script_to_index_.Lookup(&script);
|
|
|
|
if (pair != NULL) {
|
|
|
|
return pair->index_;
|
|
|
|
}
|
|
|
|
// DWARF file numbers start from 1.
|
|
|
|
intptr_t index = scripts_.length() + 1;
|
|
|
|
const Script& zone_script = Script::ZoneHandle(zone_, script.raw());
|
|
|
|
script_to_index_.Insert(ScriptIndexPair(&zone_script, index));
|
|
|
|
scripts_.Add(&zone_script);
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t Dwarf::LookupFunction(const Function& function) {
|
2018-02-16 20:48:59 +00:00
|
|
|
RELEASE_ASSERT(!function.IsNull());
|
2017-03-20 20:02:41 +00:00
|
|
|
FunctionIndexPair* pair = function_to_index_.Lookup(&function);
|
|
|
|
if (pair == NULL) {
|
|
|
|
FATAL1("Function detected too late during DWARF generation: %s",
|
|
|
|
function.ToCString());
|
|
|
|
}
|
|
|
|
return pair->index_;
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t Dwarf::LookupScript(const Script& script) {
|
2018-02-16 20:48:59 +00:00
|
|
|
RELEASE_ASSERT(!script.IsNull());
|
2017-03-20 20:02:41 +00:00
|
|
|
ScriptIndexPair* pair = script_to_index_.Lookup(&script);
|
|
|
|
if (pair == NULL) {
|
|
|
|
FATAL1("Script detected too late during DWARF generation: %s",
|
|
|
|
script.ToCString());
|
|
|
|
}
|
|
|
|
return pair->index_;
|
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
void Dwarf::WriteAbbreviations(DwarfWriteStream* stream) {
|
2019-05-28 18:48:57 +00:00
|
|
|
// Dwarf data mostly takes the form of a tree, whose nodes are called
|
|
|
|
// DIEs. Each DIE begins with an abbreviation code, and the abbreviation
|
|
|
|
// describes the attributes of that DIE and their representation.
|
2017-03-20 20:02:41 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->uleb128(kCompilationUnit); // Abbrev code.
|
|
|
|
stream->uleb128(DW_TAG_compile_unit); // Type.
|
|
|
|
stream->u1(DW_CHILDREN_yes);
|
|
|
|
stream->uleb128(DW_AT_name); // Start of attributes.
|
|
|
|
stream->uleb128(DW_FORM_string);
|
|
|
|
stream->uleb128(DW_AT_producer);
|
|
|
|
stream->uleb128(DW_FORM_string);
|
|
|
|
stream->uleb128(DW_AT_comp_dir);
|
|
|
|
stream->uleb128(DW_FORM_string);
|
|
|
|
stream->uleb128(DW_AT_low_pc);
|
|
|
|
stream->uleb128(DW_FORM_addr);
|
|
|
|
stream->uleb128(DW_AT_high_pc);
|
|
|
|
stream->uleb128(DW_FORM_addr);
|
|
|
|
stream->uleb128(DW_AT_stmt_list);
|
|
|
|
stream->uleb128(DW_FORM_sec_offset);
|
|
|
|
stream->uleb128(0);
|
|
|
|
stream->uleb128(0); // End of attributes.
|
|
|
|
|
|
|
|
stream->uleb128(kAbstractFunction); // Abbrev code.
|
|
|
|
stream->uleb128(DW_TAG_subprogram); // Type.
|
|
|
|
stream->u1(DW_CHILDREN_yes);
|
|
|
|
stream->uleb128(DW_AT_name); // Start of attributes.
|
|
|
|
stream->uleb128(DW_FORM_string);
|
|
|
|
stream->uleb128(DW_AT_decl_file);
|
|
|
|
stream->uleb128(DW_FORM_udata);
|
|
|
|
stream->uleb128(DW_AT_inline);
|
|
|
|
stream->uleb128(DW_FORM_udata);
|
|
|
|
stream->uleb128(0);
|
|
|
|
stream->uleb128(0); // End of attributes.
|
|
|
|
|
|
|
|
stream->uleb128(kConcreteFunction); // Abbrev code.
|
|
|
|
stream->uleb128(DW_TAG_subprogram); // Type.
|
|
|
|
stream->u1(DW_CHILDREN_yes);
|
|
|
|
stream->uleb128(DW_AT_abstract_origin); // Start of attributes.
|
|
|
|
stream->uleb128(DW_FORM_ref4);
|
|
|
|
stream->uleb128(DW_AT_low_pc);
|
|
|
|
stream->uleb128(DW_FORM_addr);
|
|
|
|
stream->uleb128(DW_AT_high_pc);
|
|
|
|
stream->uleb128(DW_FORM_addr);
|
|
|
|
stream->uleb128(0);
|
|
|
|
stream->uleb128(0); // End of attributes.
|
|
|
|
|
|
|
|
stream->uleb128(kInlinedFunction); // Abbrev code.
|
|
|
|
stream->uleb128(DW_TAG_inlined_subroutine); // Type.
|
|
|
|
stream->u1(DW_CHILDREN_yes);
|
|
|
|
stream->uleb128(DW_AT_abstract_origin); // Start of attributes.
|
|
|
|
stream->uleb128(DW_FORM_ref4);
|
|
|
|
stream->uleb128(DW_AT_low_pc);
|
|
|
|
stream->uleb128(DW_FORM_addr);
|
|
|
|
stream->uleb128(DW_AT_high_pc);
|
|
|
|
stream->uleb128(DW_FORM_addr);
|
|
|
|
stream->uleb128(DW_AT_call_file);
|
|
|
|
stream->uleb128(DW_FORM_udata);
|
|
|
|
stream->uleb128(DW_AT_call_line);
|
|
|
|
stream->uleb128(DW_FORM_udata);
|
[vm/aot] Reland "Keep column information when possible for precompiled mode."
Changes:
Doing this always in precompiled mode meant increased data segment sizes
when CodeSourceMaps are stored, since encoded line/column information is
larger in the LEB-like encoding used. Now we only store column
information when we produce non-symbolic stacks, since the increased
space needed to store the columns is instead in DWARF sections and can
be stripped or elided.
Original description:
Previously, we passed line number information to the stack trace printer
and to DWARF by changing the non-special positions in the CodeSourceMap
to line numbers in precompiled mode. However, doing this lost column
information.
We get the column information back in the majority of cases by encoding
the line number and column information when neither is too large to pack
together into 30 bits. (Here, 20 bits for line and 10 bits for column.)
Otherwise, we just store the line information as before, though due to
using a bit to encode whether column info exists, it's reduced to 30
bits. If the line info is too big for that, we just return kNoSourcePos.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-linux-release-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: Ia8baee71468da6100a170fa305d03059ffd17f78
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151822
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-06-19 13:50:03 +00:00
|
|
|
stream->uleb128(DW_AT_call_column);
|
|
|
|
stream->uleb128(DW_FORM_udata);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->uleb128(0);
|
|
|
|
stream->uleb128(0); // End of attributes.
|
|
|
|
|
|
|
|
stream->uleb128(0); // End of abbreviations.
|
2017-03-20 20:02:41 +00:00
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
void Dwarf::WriteDebugInfo(DwarfWriteStream* stream) {
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
SnapshotTextObjectNamer namer(zone_);
|
2019-10-25 11:53:14 +00:00
|
|
|
|
2019-05-28 18:48:57 +00:00
|
|
|
// 7.5.1.1 Compilation Unit Header
|
2017-03-20 20:02:41 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
// Unit length.
|
|
|
|
auto const cu_prefix = "cu";
|
|
|
|
intptr_t cu_start;
|
|
|
|
intptr_t cu_size_fixup = stream->ReserveSize(cu_prefix, &cu_start);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u2(2); // DWARF version 2
|
|
|
|
stream->u4(0); // debug_abbrev_offset
|
|
|
|
stream->u1(compiler::target::kWordSize); // address_size
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
// Compilation Unit DIE. We describe the entire Dart program as a single
|
|
|
|
// compilation unit. Note we write attributes in the same order we declared
|
|
|
|
// them in our abbreviation above in WriteAbbreviations.
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->uleb128(kCompilationUnit);
|
2017-03-20 20:02:41 +00:00
|
|
|
const Library& root_library = Library::Handle(
|
|
|
|
zone_, Isolate::Current()->object_store()->root_library());
|
|
|
|
const String& root_uri = String::Handle(zone_, root_library.url());
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->string(root_uri.ToCString()); // DW_AT_name
|
|
|
|
stream->string("Dart VM"); // DW_AT_producer
|
|
|
|
stream->string(""); // DW_AT_comp_dir
|
|
|
|
|
|
|
|
// DW_AT_low_pc
|
|
|
|
// The lowest instruction address in this object file that is part of our
|
|
|
|
// compilation unit. Dwarf consumers use this to quickly decide which
|
|
|
|
// compilation unit DIE to consult for a given pc.
|
|
|
|
stream->OffsetFromSymbol(kIsolateSnapshotInstructionsAsmSymbol, 0);
|
|
|
|
|
|
|
|
// DW_AT_high_pc
|
|
|
|
// The highest instruction address in this object file that is part of our
|
|
|
|
// compilation unit. Dwarf consumers use this to quickly decide which
|
|
|
|
// compilation unit DIE to consult for a given pc.
|
|
|
|
intptr_t last_code_index = codes_.length() - 1;
|
|
|
|
const Code& last_code = *(codes_[last_code_index]);
|
|
|
|
auto const last_code_name = namer.SnapshotNameFor(last_code_index, last_code);
|
|
|
|
stream->OffsetFromSymbol(last_code_name, last_code.Size());
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
// DW_AT_stmt_list (offset into .debug_line)
|
|
|
|
// Indicates which line number program is associated with this compilation
|
|
|
|
// unit. We only emit a single line number program.
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u4(0);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
WriteAbstractFunctions(stream);
|
|
|
|
WriteConcreteFunctions(stream);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->uleb128(0); // End of children.
|
2017-03-20 20:02:41 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->uleb128(0); // End of entries.
|
|
|
|
stream->SetSize(cu_size_fixup, cu_prefix, cu_start);
|
2017-03-20 20:02:41 +00:00
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
void Dwarf::WriteAbstractFunctions(DwarfWriteStream* stream) {
|
2017-03-20 20:02:41 +00:00
|
|
|
Script& script = Script::Handle(zone_);
|
|
|
|
String& name = String::Handle(zone_);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->InitializeAbstractOrigins(functions_.length());
|
2020-05-13 15:43:11 +00:00
|
|
|
// By the point we're creating DWARF information, scripts have already lost
|
[vm/aot] Reland "Keep column information when possible for precompiled mode."
Changes:
Doing this always in precompiled mode meant increased data segment sizes
when CodeSourceMaps are stored, since encoded line/column information is
larger in the LEB-like encoding used. Now we only store column
information when we produce non-symbolic stacks, since the increased
space needed to store the columns is instead in DWARF sections and can
be stripped or elided.
Original description:
Previously, we passed line number information to the stack trace printer
and to DWARF by changing the non-special positions in the CodeSourceMap
to line numbers in precompiled mode. However, doing this lost column
information.
We get the column information back in the majority of cases by encoding
the line number and column information when neither is too large to pack
together into 30 bits. (Here, 20 bits for line and 10 bits for column.)
Otherwise, we just store the line information as before, though due to
using a bit to encode whether column info exists, it's reduced to 30
bits. If the line info is too big for that, we just return kNoSourcePos.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-linux-release-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: Ia8baee71468da6100a170fa305d03059ffd17f78
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151822
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-06-19 13:50:03 +00:00
|
|
|
// their token stream and we can't look up their line number or column
|
|
|
|
// information, hence the lack of DW_AT_decl_line and DW_AT_decl_column.
|
2017-03-20 20:02:41 +00:00
|
|
|
for (intptr_t i = 0; i < functions_.length(); i++) {
|
|
|
|
const Function& function = *(functions_[i]);
|
|
|
|
name = function.QualifiedUserVisibleName();
|
|
|
|
script = function.script();
|
2019-12-18 14:14:41 +00:00
|
|
|
const intptr_t file = LookupScript(script);
|
|
|
|
auto const name_cstr = Deobfuscate(name.ToCString());
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->RegisterAbstractOrigin(i);
|
|
|
|
stream->uleb128(kAbstractFunction);
|
|
|
|
stream->string(name_cstr); // DW_AT_name
|
|
|
|
stream->uleb128(file); // DW_AT_decl_file
|
|
|
|
stream->uleb128(DW_INL_inlined); // DW_AT_inline
|
|
|
|
stream->uleb128(0); // End of children.
|
2017-03-20 20:02:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
void Dwarf::WriteConcreteFunctions(DwarfWriteStream* stream) {
|
2017-03-20 20:02:41 +00:00
|
|
|
Function& function = Function::Handle(zone_);
|
|
|
|
Script& script = Script::Handle(zone_);
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
SnapshotTextObjectNamer namer(zone_);
|
2017-03-20 20:02:41 +00:00
|
|
|
for (intptr_t i = 0; i < codes_.length(); i++) {
|
|
|
|
const Code& code = *(codes_[i]);
|
2018-02-16 20:48:59 +00:00
|
|
|
RELEASE_ASSERT(!code.IsNull());
|
2017-03-20 20:02:41 +00:00
|
|
|
if (!code.IsFunctionCode()) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-05-28 18:48:57 +00:00
|
|
|
|
2017-03-20 20:02:41 +00:00
|
|
|
function = code.function();
|
|
|
|
intptr_t function_index = LookupFunction(function);
|
|
|
|
script = function.script();
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
const char* asm_name = namer.SnapshotNameFor(i, code);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->uleb128(kConcreteFunction);
|
2017-03-20 20:02:41 +00:00
|
|
|
// DW_AT_abstract_origin
|
|
|
|
// References a node written above in WriteAbstractFunctions.
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->AbstractOrigin(function_index);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
// DW_AT_low_pc
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->OffsetFromSymbol(asm_name, 0);
|
|
|
|
// DW_AT_high_pc
|
|
|
|
stream->OffsetFromSymbol(asm_name, code.Size());
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
InliningNode* node = ExpandInliningTree(code);
|
|
|
|
if (node != NULL) {
|
|
|
|
for (InliningNode* child = node->children_head; child != NULL;
|
|
|
|
child = child->children_next) {
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
WriteInliningNode(stream, child, asm_name, script, &namer);
|
2017-03-20 20:02:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->uleb128(0); // End of children.
|
2017-03-20 20:02:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-22 09:29:45 +00:00
|
|
|
static DwarfPosition ReadPosition(ReadStream* stream) {
|
|
|
|
const intptr_t line = stream->Read<int32_t>();
|
|
|
|
if (!FLAG_dwarf_stack_traces_mode) {
|
|
|
|
return DwarfPosition(line);
|
|
|
|
}
|
|
|
|
const intptr_t column = stream->Read<int32_t>();
|
|
|
|
return DwarfPosition(line, column);
|
|
|
|
}
|
|
|
|
|
2017-03-20 20:02:41 +00:00
|
|
|
// Our state machine encodes position metadata such that we don't know the
|
|
|
|
// end pc for an inlined function until it is popped, but DWARF DIEs encode
|
|
|
|
// it where the function is pushed. We expand the state transitions into
|
|
|
|
// an in-memory tree to do the conversion.
|
|
|
|
InliningNode* Dwarf::ExpandInliningTree(const Code& code) {
|
|
|
|
const CodeSourceMap& map =
|
|
|
|
CodeSourceMap::Handle(zone_, code.code_source_map());
|
|
|
|
if (map.IsNull()) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
const Array& functions = Array::Handle(zone_, code.inlined_id_to_function());
|
2018-02-09 18:49:39 +00:00
|
|
|
const Function& root_function = Function::ZoneHandle(zone_, code.function());
|
2018-02-16 23:18:11 +00:00
|
|
|
if (root_function.IsNull()) {
|
|
|
|
FATAL1("Wherefore art thou functionless code, %s?\n", code.ToCString());
|
|
|
|
}
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
GrowableArray<InliningNode*> node_stack(zone_, 4);
|
2020-06-22 09:29:45 +00:00
|
|
|
GrowableArray<DwarfPosition> token_positions(zone_, 4);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
NoSafepointScope no_safepoint;
|
|
|
|
ReadStream stream(map.Data(), map.Length());
|
|
|
|
|
|
|
|
int32_t current_pc_offset = 0;
|
2020-06-22 09:29:45 +00:00
|
|
|
token_positions.Add(kNoDwarfPositionInfo);
|
2017-03-20 20:02:41 +00:00
|
|
|
InliningNode* root_node =
|
2020-06-22 09:29:45 +00:00
|
|
|
new (zone_) InliningNode(root_function, token_positions.Last(), 0);
|
2017-03-20 20:02:41 +00:00
|
|
|
root_node->end_pc_offset = code.Size();
|
|
|
|
node_stack.Add(root_node);
|
|
|
|
|
|
|
|
while (stream.PendingBytes() > 0) {
|
|
|
|
uint8_t opcode = stream.Read<uint8_t>();
|
|
|
|
switch (opcode) {
|
|
|
|
case CodeSourceMapBuilder::kChangePosition: {
|
2020-06-22 09:29:45 +00:00
|
|
|
token_positions[token_positions.length() - 1] = ReadPosition(&stream);
|
2017-03-20 20:02:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeSourceMapBuilder::kAdvancePC: {
|
|
|
|
int32_t delta = stream.Read<int32_t>();
|
|
|
|
current_pc_offset += delta;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeSourceMapBuilder::kPushFunction: {
|
|
|
|
int32_t func = stream.Read<int32_t>();
|
|
|
|
const Function& child_func =
|
2018-02-09 18:49:39 +00:00
|
|
|
Function::ZoneHandle(zone_, Function::RawCast(functions.At(func)));
|
2020-06-22 09:29:45 +00:00
|
|
|
InliningNode* child_node = new (zone_)
|
|
|
|
InliningNode(child_func, token_positions.Last(), current_pc_offset);
|
2017-03-20 20:02:41 +00:00
|
|
|
node_stack.Last()->AppendChild(child_node);
|
|
|
|
node_stack.Add(child_node);
|
2020-06-22 09:29:45 +00:00
|
|
|
token_positions.Add(kNoDwarfPositionInfo);
|
2017-03-20 20:02:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeSourceMapBuilder::kPopFunction: {
|
|
|
|
// We never pop the root function.
|
|
|
|
ASSERT(node_stack.length() > 1);
|
|
|
|
ASSERT(token_positions.length() > 1);
|
|
|
|
node_stack.Last()->end_pc_offset = current_pc_offset;
|
|
|
|
node_stack.RemoveLast();
|
|
|
|
token_positions.RemoveLast();
|
|
|
|
break;
|
|
|
|
}
|
2018-04-26 20:33:15 +00:00
|
|
|
case CodeSourceMapBuilder::kNullCheck: {
|
|
|
|
stream.Read<int32_t>();
|
|
|
|
break;
|
|
|
|
}
|
2017-03-20 20:02:41 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while (node_stack.length() > 1) {
|
|
|
|
node_stack.Last()->end_pc_offset = current_pc_offset;
|
|
|
|
node_stack.RemoveLast();
|
|
|
|
token_positions.RemoveLast();
|
|
|
|
}
|
|
|
|
ASSERT(node_stack[0] == root_node);
|
|
|
|
return root_node;
|
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
void Dwarf::WriteInliningNode(DwarfWriteStream* stream,
|
|
|
|
InliningNode* node,
|
|
|
|
const char* root_asm_name,
|
2019-10-25 11:53:14 +00:00
|
|
|
const Script& parent_script,
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
SnapshotTextObjectNamer* namer) {
|
2017-03-20 20:02:41 +00:00
|
|
|
intptr_t file = LookupScript(parent_script);
|
|
|
|
intptr_t function_index = LookupFunction(node->function);
|
|
|
|
const Script& script = Script::Handle(zone_, node->function.script());
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->uleb128(kInlinedFunction);
|
2017-03-20 20:02:41 +00:00
|
|
|
// DW_AT_abstract_origin
|
|
|
|
// References a node written above in WriteAbstractFunctions.
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->AbstractOrigin(function_index);
|
2019-10-25 11:53:14 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
// DW_AT_low_pc
|
|
|
|
stream->OffsetFromSymbol(root_asm_name, node->start_pc_offset);
|
|
|
|
// DW_AT_high_pc
|
|
|
|
stream->OffsetFromSymbol(root_asm_name, node->end_pc_offset);
|
2017-03-20 20:02:41 +00:00
|
|
|
// DW_AT_call_file
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->uleb128(file);
|
2017-03-20 20:02:41 +00:00
|
|
|
// DW_AT_call_line
|
2020-06-22 09:29:45 +00:00
|
|
|
stream->uleb128(node->position.line());
|
[vm/aot] Reland "Keep column information when possible for precompiled mode."
Changes:
Doing this always in precompiled mode meant increased data segment sizes
when CodeSourceMaps are stored, since encoded line/column information is
larger in the LEB-like encoding used. Now we only store column
information when we produce non-symbolic stacks, since the increased
space needed to store the columns is instead in DWARF sections and can
be stripped or elided.
Original description:
Previously, we passed line number information to the stack trace printer
and to DWARF by changing the non-special positions in the CodeSourceMap
to line numbers in precompiled mode. However, doing this lost column
information.
We get the column information back in the majority of cases by encoding
the line number and column information when neither is too large to pack
together into 30 bits. (Here, 20 bits for line and 10 bits for column.)
Otherwise, we just store the line information as before, though due to
using a bit to encode whether column info exists, it's reduced to 30
bits. If the line info is too big for that, we just return kNoSourcePos.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-linux-release-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: Ia8baee71468da6100a170fa305d03059ffd17f78
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151822
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-06-19 13:50:03 +00:00
|
|
|
// DW_at_call_column
|
2020-06-22 09:29:45 +00:00
|
|
|
stream->uleb128(node->position.column());
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
for (InliningNode* child = node->children_head; child != NULL;
|
|
|
|
child = child->children_next) {
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
WriteInliningNode(stream, child, root_asm_name, script, namer);
|
2017-03-20 20:02:41 +00:00
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->uleb128(0); // End of children.
|
2017-03-20 20:02:41 +00:00
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
void Dwarf::WriteLineNumberProgram(DwarfWriteStream* stream) {
|
2017-03-20 20:02:41 +00:00
|
|
|
// 6.2.4 The Line Number Program Header
|
|
|
|
|
|
|
|
// 1. unit_length. This encoding implies 32-bit DWARF.
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
auto const line_prefix = "line";
|
|
|
|
intptr_t line_start;
|
|
|
|
intptr_t line_size_fixup = stream->ReserveSize(line_prefix, &line_start);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u2(2); // 2. DWARF version 2
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
// 3. header_length
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
auto const lineheader_prefix = "lineheader";
|
|
|
|
intptr_t lineheader_start;
|
|
|
|
intptr_t lineheader_size_fixup =
|
|
|
|
stream->ReserveSize(lineheader_prefix, &lineheader_start);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u1(1); // 4. minimum_instruction_length
|
|
|
|
stream->u1(1); // 5. default_is_stmt (true for compatibility with dsymutil).
|
|
|
|
stream->u1(0); // 6. line_base
|
|
|
|
stream->u1(1); // 7. line_range
|
|
|
|
stream->u1(13); // 8. opcode_base (12 standard opcodes in Dwarf 2)
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
// 9. standard_opcode_lengths
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u1(0); // DW_LNS_copy, 0 operands
|
|
|
|
stream->u1(1); // DW_LNS_advance_pc, 1 operands
|
|
|
|
stream->u1(1); // DW_LNS_advance_list, 1 operands
|
|
|
|
stream->u1(1); // DW_LNS_set_file, 1 operands
|
|
|
|
stream->u1(1); // DW_LNS_set_column, 1 operands
|
|
|
|
stream->u1(0); // DW_LNS_negate_stmt, 0 operands
|
|
|
|
stream->u1(0); // DW_LNS_set_basic_block, 0 operands
|
|
|
|
stream->u1(0); // DW_LNS_const_add_pc, 0 operands
|
|
|
|
stream->u1(1); // DW_LNS_fixed_advance_pc, 1 operands
|
|
|
|
stream->u1(0); // DW_LNS_set_prolog_end, 0 operands
|
|
|
|
stream->u1(0); // DW_LNS_set_epligoue_begin, 0 operands
|
|
|
|
stream->u1(1); // DW_LNS_set_isa, 1 operands
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
// 10. include_directories (sequence of path names)
|
|
|
|
// We don't emit any because we use full paths below.
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u1(0);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
// 11. file_names (sequence of file entries)
|
|
|
|
String& uri = String::Handle(zone_);
|
|
|
|
for (intptr_t i = 0; i < scripts_.length(); i++) {
|
|
|
|
const Script& script = *(scripts_[i]);
|
2019-05-01 00:04:44 +00:00
|
|
|
uri = script.url();
|
2019-12-18 14:14:41 +00:00
|
|
|
auto const uri_cstr = Deobfuscate(uri.ToCString());
|
|
|
|
RELEASE_ASSERT(strlen(uri_cstr) != 0);
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->string(uri_cstr); // NOLINT
|
|
|
|
stream->uleb128(0); // Include directory index.
|
|
|
|
stream->uleb128(0); // File modification time.
|
|
|
|
stream->uleb128(0); // File length.
|
2019-05-28 18:48:57 +00:00
|
|
|
}
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u1(0); // End of file names.
|
|
|
|
stream->SetSize(lineheader_size_fixup, lineheader_prefix, lineheader_start);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
// 6.2.5 The Line Number Program
|
|
|
|
|
[vm/aot] Reland "Keep column information when possible for precompiled mode."
Changes:
Doing this always in precompiled mode meant increased data segment sizes
when CodeSourceMaps are stored, since encoded line/column information is
larger in the LEB-like encoding used. Now we only store column
information when we produce non-symbolic stacks, since the increased
space needed to store the columns is instead in DWARF sections and can
be stripped or elided.
Original description:
Previously, we passed line number information to the stack trace printer
and to DWARF by changing the non-special positions in the CodeSourceMap
to line numbers in precompiled mode. However, doing this lost column
information.
We get the column information back in the majority of cases by encoding
the line number and column information when neither is too large to pack
together into 30 bits. (Here, 20 bits for line and 10 bits for column.)
Otherwise, we just store the line information as before, though due to
using a bit to encode whether column info exists, it's reduced to 30
bits. If the line info is too big for that, we just return kNoSourcePos.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-linux-release-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: Ia8baee71468da6100a170fa305d03059ffd17f78
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151822
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-06-19 13:50:03 +00:00
|
|
|
// The initial values for the line number program state machine registers
|
|
|
|
// according to the DWARF standard.
|
|
|
|
intptr_t previous_pc_offset = 0;
|
2017-03-20 20:02:41 +00:00
|
|
|
intptr_t previous_file = 1;
|
|
|
|
intptr_t previous_line = 1;
|
[vm/aot] Reland "Keep column information when possible for precompiled mode."
Changes:
Doing this always in precompiled mode meant increased data segment sizes
when CodeSourceMaps are stored, since encoded line/column information is
larger in the LEB-like encoding used. Now we only store column
information when we produce non-symbolic stacks, since the increased
space needed to store the columns is instead in DWARF sections and can
be stripped or elided.
Original description:
Previously, we passed line number information to the stack trace printer
and to DWARF by changing the non-special positions in the CodeSourceMap
to line numbers in precompiled mode. However, doing this lost column
information.
We get the column information back in the majority of cases by encoding
the line number and column information when neither is too large to pack
together into 30 bits. (Here, 20 bits for line and 10 bits for column.)
Otherwise, we just store the line information as before, though due to
using a bit to encode whether column info exists, it's reduced to 30
bits. If the line info is too big for that, we just return kNoSourcePos.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-linux-release-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: Ia8baee71468da6100a170fa305d03059ffd17f78
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151822
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-06-19 13:50:03 +00:00
|
|
|
intptr_t previous_column = 0;
|
|
|
|
// Other info not stored in the state machine registers.
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
const char* previous_asm_name = nullptr;
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
Function& root_function = Function::Handle(zone_);
|
|
|
|
Script& script = Script::Handle(zone_);
|
|
|
|
CodeSourceMap& map = CodeSourceMap::Handle(zone_);
|
|
|
|
Array& functions = Array::Handle(zone_);
|
|
|
|
GrowableArray<const Function*> function_stack(zone_, 8);
|
2020-06-22 09:29:45 +00:00
|
|
|
GrowableArray<DwarfPosition> token_positions(zone_, 8);
|
[vm] Reland two dispatch table related changes as a single change.
These changes were originally submitted separately on different days,
and a major performance regression was seen after the first change
when creating snapshots that led to both being reverted. However,
that performance regression should be addressed by the followup.
First change:
"[vm] Treat the dispatch table as a root in the snapshot.
Additional changes:
* Only serialize a dispatch table in precompiled snapshots.
* Add information in v8 snapshot profiles for the dispatch table.
* Fix a typo in a field name.
* Print the number of Instructions objects (or payloads, for
precompiled bare instructions mode) in the fake cluster for
the data section.
* Fix v8 snapshots profiles so objects in memory mapped segments
and only those are prefixed with "(RO) ".
* Add names for Instructions objects in v8 snapshot profiles
when we can use the assembly namer.
* Add command line flag for old #define'd false flag."
Second change:
"[vm/aot] Keep GC-visible references to dispatch table Code entries.
This change splits dispatch table handling into four distinct
parts:
* The dispatch table generator does not make a dispatch table
directly, but rather creates an Array that contains the Code
objects for dispatch table entries.
* The precompiler takes this Array and puts it in the object
store, which makes it a new GC root.
* The serializer takes this information and serializes the
dispatch table information in the same form as before.
* The deserializer creates a DispatchTable object and populates
it using the serialized information.
The change in the precompiler ensures that the Code objects
used in the dispatch table have GC-visible references. Thus,
even if all other references to them from the other GC roots
were removed, they would be accessible in the serializer in
the case of a GC pass between the precompiler and serializer.
This change also means that the serializer can retrieve and
trace the Code objects directly rather than first looking up
the Code objects by their entry point."
Bug: https://github.com/dart-lang/sdk/issues/41022
Change-Id: I52c83b0536fc588da0bef9aed1f0c72e8ee4663f
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139285
Commit-Queue: Teagan Strickland <sstrickl@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-03-13 17:19:52 +00:00
|
|
|
SnapshotTextObjectNamer namer(zone_);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
for (intptr_t i = 0; i < codes_.length(); i++) {
|
|
|
|
const Code& code = *(codes_[i]);
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
auto const asm_name = namer.SnapshotNameFor(i, code);
|
2019-05-28 18:48:57 +00:00
|
|
|
|
2017-03-20 20:02:41 +00:00
|
|
|
map = code.code_source_map();
|
|
|
|
if (map.IsNull()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
root_function = code.function();
|
|
|
|
functions = code.inlined_id_to_function();
|
|
|
|
|
|
|
|
NoSafepointScope no_safepoint;
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
ReadStream code_map_stream(map.Data(), map.Length());
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
function_stack.Clear();
|
|
|
|
token_positions.Clear();
|
|
|
|
|
|
|
|
int32_t current_pc_offset = 0;
|
|
|
|
function_stack.Add(&root_function);
|
2020-06-22 09:29:45 +00:00
|
|
|
token_positions.Add(kNoDwarfPositionInfo);
|
2017-03-20 20:02:41 +00:00
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
while (code_map_stream.PendingBytes() > 0) {
|
|
|
|
uint8_t opcode = code_map_stream.Read<uint8_t>();
|
2017-03-20 20:02:41 +00:00
|
|
|
switch (opcode) {
|
|
|
|
case CodeSourceMapBuilder::kChangePosition: {
|
|
|
|
token_positions[token_positions.length() - 1] =
|
2020-06-22 09:29:45 +00:00
|
|
|
ReadPosition(&code_map_stream);
|
2017-03-20 20:02:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeSourceMapBuilder::kAdvancePC: {
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
int32_t delta = code_map_stream.Read<int32_t>();
|
2017-03-20 20:02:41 +00:00
|
|
|
current_pc_offset += delta;
|
|
|
|
|
|
|
|
const Function& function = *(function_stack.Last());
|
|
|
|
script = function.script();
|
|
|
|
intptr_t file = LookupScript(script);
|
|
|
|
|
|
|
|
// 1. Update LNP file.
|
|
|
|
if (file != previous_file) {
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u1(DW_LNS_set_file);
|
|
|
|
stream->uleb128(file);
|
2017-03-20 20:02:41 +00:00
|
|
|
previous_file = file;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2. Update LNP line.
|
2020-06-22 09:29:45 +00:00
|
|
|
const intptr_t line = token_positions.Last().line();
|
|
|
|
const intptr_t column = token_positions.Last().column();
|
2017-03-20 20:02:41 +00:00
|
|
|
if (line != previous_line) {
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u1(DW_LNS_advance_line);
|
|
|
|
stream->sleb128(line - previous_line);
|
2017-03-20 20:02:41 +00:00
|
|
|
previous_line = line;
|
|
|
|
}
|
[vm/aot] Reland "Keep column information when possible for precompiled mode."
Changes:
Doing this always in precompiled mode meant increased data segment sizes
when CodeSourceMaps are stored, since encoded line/column information is
larger in the LEB-like encoding used. Now we only store column
information when we produce non-symbolic stacks, since the increased
space needed to store the columns is instead in DWARF sections and can
be stripped or elided.
Original description:
Previously, we passed line number information to the stack trace printer
and to DWARF by changing the non-special positions in the CodeSourceMap
to line numbers in precompiled mode. However, doing this lost column
information.
We get the column information back in the majority of cases by encoding
the line number and column information when neither is too large to pack
together into 30 bits. (Here, 20 bits for line and 10 bits for column.)
Otherwise, we just store the line information as before, though due to
using a bit to encode whether column info exists, it's reduced to 30
bits. If the line info is too big for that, we just return kNoSourcePos.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-linux-release-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: Ia8baee71468da6100a170fa305d03059ffd17f78
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151822
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-06-19 13:50:03 +00:00
|
|
|
if (column != previous_column) {
|
|
|
|
stream->u1(DW_LNS_set_column);
|
|
|
|
stream->uleb128(column);
|
|
|
|
previous_column = column;
|
|
|
|
}
|
2017-03-20 20:02:41 +00:00
|
|
|
|
2020-05-11 08:41:17 +00:00
|
|
|
// 3. Emit LNP row if the address register has been updated to a
|
|
|
|
// non-zero value (dartbug.com/41756).
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
if (previous_asm_name != nullptr) {
|
|
|
|
stream->u1(DW_LNS_copy);
|
2020-05-11 08:41:17 +00:00
|
|
|
}
|
2017-03-22 17:30:02 +00:00
|
|
|
|
|
|
|
// 4. Update LNP pc.
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
if (previous_asm_name == nullptr) {
|
|
|
|
auto const instr_size = 1 + compiler::target::kWordSize;
|
|
|
|
stream->u1(0); // This is an extended opcode
|
|
|
|
stream->u1(instr_size); // that is 5 or 9 bytes long
|
|
|
|
stream->u1(DW_LNE_set_address);
|
|
|
|
stream->OffsetFromSymbol(asm_name, current_pc_offset);
|
2017-03-20 20:02:41 +00:00
|
|
|
} else {
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u1(DW_LNS_advance_pc);
|
|
|
|
stream->DistanceBetweenSymbolOffsets(asm_name, current_pc_offset,
|
|
|
|
previous_asm_name,
|
|
|
|
previous_pc_offset);
|
2017-03-20 20:02:41 +00:00
|
|
|
}
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
previous_asm_name = asm_name;
|
2017-03-20 20:02:41 +00:00
|
|
|
previous_pc_offset = current_pc_offset;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeSourceMapBuilder::kPushFunction: {
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
int32_t func_index = code_map_stream.Read<int32_t>();
|
2017-03-20 20:02:41 +00:00
|
|
|
const Function& child_func = Function::Handle(
|
|
|
|
zone_, Function::RawCast(functions.At(func_index)));
|
|
|
|
function_stack.Add(&child_func);
|
2020-06-22 09:29:45 +00:00
|
|
|
token_positions.Add(kNoDwarfPositionInfo);
|
2017-03-20 20:02:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeSourceMapBuilder::kPopFunction: {
|
|
|
|
// We never pop the root function.
|
|
|
|
ASSERT(function_stack.length() > 1);
|
|
|
|
ASSERT(token_positions.length() > 1);
|
|
|
|
function_stack.RemoveLast();
|
|
|
|
token_positions.RemoveLast();
|
|
|
|
break;
|
|
|
|
}
|
2018-04-26 20:33:15 +00:00
|
|
|
case CodeSourceMapBuilder::kNullCheck: {
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
code_map_stream.Read<int32_t>();
|
2018-04-26 20:33:15 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-03-20 20:02:41 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
// Advance pc to end of the compilation unit if not already there.
|
[vm] Initial implementation of deferred loading.
(Assignment of libraries to loading units is already done in the kernel generation step.)
After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit.
All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size.
Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units.
Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number.
Embedder's guide:
At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths.
At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error].
Bug: https://github.com/dart-lang/sdk/issues/41974
Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
|
|
|
if (codes_.length() != 0) {
|
|
|
|
const intptr_t last_code_index = codes_.length() - 1;
|
|
|
|
const Code& last_code = *(codes_[last_code_index]);
|
|
|
|
const intptr_t last_pc_offset = last_code.Size();
|
|
|
|
const char* last_asm_name =
|
|
|
|
namer.SnapshotNameFor(last_code_index, last_code);
|
|
|
|
|
|
|
|
stream->u1(DW_LNS_advance_pc);
|
|
|
|
if (previous_asm_name != nullptr) {
|
|
|
|
stream->DistanceBetweenSymbolOffsets(
|
|
|
|
last_asm_name, last_pc_offset, previous_asm_name, previous_pc_offset);
|
|
|
|
} else {
|
|
|
|
// No LNP entries (e.g., only stub code).
|
|
|
|
ASSERT(previous_pc_offset == 0);
|
|
|
|
stream->uleb128(last_pc_offset);
|
|
|
|
}
|
|
|
|
}
|
2017-03-20 20:02:41 +00:00
|
|
|
|
|
|
|
// End of contiguous machine code.
|
[vm/aot] Rework Dwarf object to be output-agnostic.
Previously, we created a separate DWARF object for each possible output.
For the most part, the information stored in each DWARF object was the
same, but the DWARF object was responsible for keeping track of abstract
origin addresses (in the non-assembly case) and for actually generating
the desired output (assembly or binary).
Instead, abstract out the output formatting into a DwarfWriteStream,
whose subclasses handle both the final output format and certain details
that differ between assembly and binary outputs. With this, the DWARF
class no longer depends on having direct access to the ELF file if being
used to generate ELF sections, and as such is output agnostic.
Now, if we have one or more outputs that contain DWARF information, we
only generate a single DWARF object that is shared across these outputs.
The only additional change required is in Dwarf::AddCode(), which now
handles being called multiple times for the same Code object.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try
Change-Id: I71de887a07a673164b3ccfa7fbbab2ccef80c576
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150302
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
2020-06-11 08:57:59 +00:00
|
|
|
stream->u1(0); // This is an extended opcode
|
|
|
|
stream->u1(1); // that is 1 byte long
|
|
|
|
stream->u1(DW_LNE_end_sequence);
|
|
|
|
stream->SetSize(line_size_fixup, line_prefix, line_start);
|
2017-03-20 20:02:41 +00:00
|
|
|
}
|
|
|
|
|
2019-12-18 14:14:41 +00:00
|
|
|
const char* Dwarf::Deobfuscate(const char* cstr) {
|
|
|
|
if (reverse_obfuscation_trie_ == nullptr) return cstr;
|
|
|
|
TextBuffer buffer(256);
|
|
|
|
// Used to avoid Zone-allocating strings if no deobfuscation was performed.
|
|
|
|
bool changed = false;
|
|
|
|
intptr_t i = 0;
|
|
|
|
while (cstr[i] != '\0') {
|
|
|
|
intptr_t offset;
|
|
|
|
auto const value = reverse_obfuscation_trie_->Lookup(cstr + i, &offset);
|
|
|
|
if (offset == 0) {
|
|
|
|
// The first character was an invalid key element (that isn't the null
|
|
|
|
// terminator due to the while condition), copy it and skip to the next.
|
|
|
|
buffer.AddChar(cstr[i++]);
|
|
|
|
} else if (value != nullptr) {
|
|
|
|
changed = true;
|
|
|
|
buffer.AddString(value);
|
|
|
|
} else {
|
|
|
|
buffer.AddRaw(reinterpret_cast<const uint8_t*>(cstr + i), offset);
|
|
|
|
}
|
|
|
|
i += offset;
|
|
|
|
}
|
|
|
|
if (!changed) return cstr;
|
2020-08-07 18:09:35 +00:00
|
|
|
return OS::SCreate(zone_, "%s", buffer.buffer());
|
2019-12-18 14:14:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Trie<const char>* Dwarf::CreateReverseObfuscationTrie(Zone* zone) {
|
|
|
|
auto const I = Thread::Current()->isolate();
|
|
|
|
auto const map_array = I->obfuscation_map();
|
|
|
|
if (map_array == nullptr) return nullptr;
|
|
|
|
|
|
|
|
Trie<const char>* trie = nullptr;
|
|
|
|
for (intptr_t i = 0; map_array[i] != nullptr; i += 2) {
|
|
|
|
auto const key = map_array[i];
|
|
|
|
auto const value = map_array[i + 1];
|
|
|
|
ASSERT(value != nullptr);
|
|
|
|
// Don't include identity mappings.
|
|
|
|
if (strcmp(key, value) == 0) continue;
|
|
|
|
// Otherwise, any value in the obfuscation map should be a valid key.
|
|
|
|
ASSERT(Trie<const char>::IsValidKey(value));
|
|
|
|
trie = Trie<const char>::AddString(zone, trie, value, key);
|
|
|
|
}
|
|
|
|
return trie;
|
|
|
|
}
|
|
|
|
|
2017-03-20 20:02:41 +00:00
|
|
|
#endif // DART_PRECOMPILER
|
|
|
|
|
|
|
|
} // namespace dart
|