class LinkerPatch { public: // Note: We explicitly specify the underlying type of the enum because GCC // would otherwise select a bigger underlying type and then complain that // 'art::LinkerPatch::patch_type_' is too small to hold all // values of 'enum class art::LinkerPatch::Type' // which is ridiculous given we have only a handful of values here. If we // choose to squeeze the Type into fewer than 8 bits, we'll have to declare // patch_type_ as an uintN_t and do explicit static_cast<>s. // // Note: Actual patching is instruction_set-dependent. enumclass Type : uint8_t {
kIntrinsicReference, // Boot image reference for an intrinsic, see IntrinsicObjects.
kBootImageRelRo,
kMethodRelative,
kMethodAppImageRelRo,
kMethodBssEntry,
kJniEntrypointRelative,
kCallRelative,
kTypeRelative,
kTypeAppImageRelRo,
kTypeBssEntry,
kPublicTypeBssEntry,
kPackageTypeBssEntry,
kStringRelative,
kStringAppImageRelRo,
kStringBssEntry,
kMethodTypeBssEntry,
kCallEntrypoint,
kBakerReadBarrierBranch,
};
private:
LinkerPatch(size_t literal_offset, Type patch_type, const DexFile* target_dex_file)
: target_dex_file_(target_dex_file),
literal_offset_(literal_offset),
patch_type_(patch_type) {
cmp1_ = 0u;
cmp2_ = 0u; // The compiler rejects methods that are too big, so the compiled code // of a single method really shouln't be anywhere close to 16MiB.
DCHECK(IsUint<24>(literal_offset));
}
const DexFile* target_dex_file_; // TODO: Clean up naming. Some patched locations are literals but others are not.
uint32_t literal_offset_ : 24; // Method code size up to 16MiB.
Type patch_type_ : 8; union {
uint32_t cmp1_; // Used for relational operators.
uint32_t boot_image_offset_; // Data to write to the boot image .data.img.rel.ro entry.
uint32_t method_idx_; // Method index for Call/Method patches.
uint32_t type_idx_; // Type index for Type patches.
uint32_t string_idx_; // String index for String patches.
uint32_t proto_idx_; // Proto index for MethodType patches.
uint32_t intrinsic_data_; // Data for IntrinsicObjects.
uint32_t entrypoint_offset_; // Entrypoint offset in the Thread object.
uint32_t baker_custom_value1_;
static_assert(sizeof(method_idx_) == sizeof(cmp1_), "needed by relational operators");
static_assert(sizeof(type_idx_) == sizeof(cmp1_), "needed by relational operators");
static_assert(sizeof(string_idx_) == sizeof(cmp1_), "needed by relational operators");
static_assert(sizeof(proto_idx_) == sizeof(cmp1_), "needed by relational operators");
static_assert(sizeof(intrinsic_data_) == sizeof(cmp1_), "needed by relational operators");
static_assert(sizeof(baker_custom_value1_) == sizeof(cmp1_), "needed by relational operators");
}; union { // Note: To avoid uninitialized padding on 64-bit systems, we use `size_t` for `cmp2_`. // This allows a hashing function to treat an array of linker patches as raw memory.
size_t cmp2_; // Used for relational operators. // Literal offset of the insn loading PC (same as literal_offset if it's the same insn, // may be different if the PC-relative addressing needs multiple insns).
uint32_t pc_insn_offset_;
uint32_t baker_custom_value2_;
static_assert(sizeof(pc_insn_offset_) <= sizeof(cmp2_), "needed by relational operators");
static_assert(sizeof(baker_custom_value2_) <= sizeof(cmp2_), "needed by relational operators");
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.