summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/elf_writer.cc2
-rw-r--r--compiler/elf_writer_quick.cc42
-rw-r--r--dex2oat/dex2oat.cc2
-rw-r--r--runtime/dwarf.h662
-rw-r--r--runtime/elf_file.cc712
-rw-r--r--runtime/elf_file.h16
6 files changed, 1101 insertions, 335 deletions
diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc
index 4c093c7..55ee18e 100644
--- a/compiler/elf_writer.cc
+++ b/compiler/elf_writer.cc
@@ -43,7 +43,7 @@ void ElfWriter::GetOatElfInformation(File* file,
size_t& oat_data_offset) {
std::string error_msg;
std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, false, false, &error_msg));
- CHECK(elf_file.get() != NULL) << error_msg;
+ CHECK(elf_file.get() != nullptr) << error_msg;
oat_loaded_size = elf_file->GetLoadedSize();
CHECK_NE(0U, oat_loaded_size);
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 78757ec..e4dcaa7 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -20,6 +20,7 @@
#include "base/unix_file/fd_file.h"
#include "buffered_output_stream.h"
#include "driver/compiler_driver.h"
+#include "dwarf.h"
#include "elf_utils.h"
#include "file_output_stream.h"
#include "globals.h"
@@ -469,9 +470,9 @@ bool ElfWriterQuick::ElfBuilder::Write() {
pieces.push_back(ElfFilePiece(".hash", hash_builder_.section_.sh_offset,
hash.data(), hash.size() * sizeof(Elf32_Word)));
pieces.push_back(ElfFilePiece(".rodata", rodata_builder_.section_.sh_offset,
- NULL, rodata_builder_.section_.sh_size));
+ nullptr, rodata_builder_.section_.sh_size));
pieces.push_back(ElfFilePiece(".text", text_builder_.section_.sh_offset,
- NULL, text_builder_.section_.sh_size));
+ nullptr, text_builder_.section_.sh_size));
if (IncludingDebugSymbols()) {
pieces.push_back(ElfFilePiece(".symtab", symtab_builder_.section_.sh_offset,
symtab.data(), symtab.size() * sizeof(Elf32_Sym)));
@@ -547,7 +548,7 @@ void ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Wor
if (tag == DT_NULL) {
return;
}
- dynamics_.push_back({NULL, tag, d_un});
+ dynamics_.push_back({nullptr, tag, d_un});
}
void ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un,
@@ -650,7 +651,7 @@ std::vector<Elf32_Word> ElfWriterQuick::ElfSymtabBuilder::GenerateHashContents()
// Lets say the state is something like this.
// +--------+ +--------+ +-----------+
// | symtab | | bucket | | chain |
- // | NULL | | 1 | | STN_UNDEF |
+ // | nullptr | | 1 | | STN_UNDEF |
// | <sym1> | | 4 | | 2 |
// | <sym2> | | | | 5 |
// | <sym3> | | | | STN_UNDEF |
@@ -821,10 +822,10 @@ bool ElfWriterQuick::Write(OatWriter* oat_writer,
bool generateDebugInformation = compiler_driver_->GetCallFrameInformation() != nullptr;
if (generateDebugInformation) {
- ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, NULL, 0, 1, 0);
- ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, NULL, 0, 1, 0);
- ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, NULL, 0, 1, 0);
- ElfRawSectionBuilder debug_frame(".debug_frame", SHT_PROGBITS, 0, NULL, 0, 4, 0);
+ ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+ ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+ ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+ ElfRawSectionBuilder debug_frame(".debug_frame", SHT_PROGBITS, 0, nullptr, 0, 4, 0);
debug_frame.SetBuffer(*compiler_driver_->GetCallFrameInformation());
FillInCFIInformation(oat_writer, debug_info.GetBuffer(),
@@ -866,31 +867,6 @@ static void PushHalf(std::vector<uint8_t>*buf, int data) {
buf->push_back((data >> 8) & 0xff);
}
-// DWARF constants needed to generate CFI information.
-enum {
- // Tag encodings.
- DW_TAG_compile_unit = 0x11,
- DW_TAG_subprogram = 0X2e,
-
- // Attribute encodings.
- DW_AT_name = 0x03,
- DW_AT_low_pc = 0x11,
- DW_AT_high_pc = 0x12,
- DW_AT_language = 0x13,
-
- // Constant encoding.
- DW_CHILDREN_no = 0x00,
- DW_CHILDREN_yes = 0x01,
-
- // Attribute form encodings.
- DW_FORM_addr = 0x01,
- DW_FORM_data1 = 0x0b,
- DW_FORM_strp = 0x0e,
-
- // Language encoding.
- DW_LANG_Java = 0x000b
-};
-
void ElfWriterQuick::FillInCFIInformation(OatWriter* oat_writer,
std::vector<uint8_t>* dbg_info,
std::vector<uint8_t>* dbg_abbrev,
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index bf04a54..280f6d0 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -875,6 +875,8 @@ static int dex2oat(int argc, char** argv) {
watch_dog_enabled = false;
} else if (option == "--gen-gdb-info") {
generate_gdb_information = true;
+ // Debug symbols are needed for gdb information.
+ include_debug_symbols = true;
} else if (option == "--no-gen-gdb-info") {
generate_gdb_information = false;
} else if (option.starts_with("-j")) {
diff --git a/runtime/dwarf.h b/runtime/dwarf.h
new file mode 100644
index 0000000..370ad95
--- /dev/null
+++ b/runtime/dwarf.h
@@ -0,0 +1,662 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_DWARF_H_
+#define ART_RUNTIME_DWARF_H_
+
+namespace art {
+
+// Based on the Dwarf 4 specification at dwarfstd.com and issues marked
+// for inclusion in Dwarf 5 on same. Values not specified in the Dwarf 4
+// standard might change or be removed in the future and may be different
+// than the values used currently by other implementations for the same trait,
+// use at your own risk.
+
+enum Tag {
+ DW_TAG_array_type = 0x01,
+ DW_TAG_class_type = 0x02,
+ DW_TAG_entry_point = 0x03,
+ DW_TAG_enumeration_type = 0x04,
+ DW_TAG_formal_parameter = 0x05,
+ DW_TAG_imported_declaration = 0x08,
+ DW_TAG_label = 0x0a,
+ DW_TAG_lexical_block = 0x0b,
+ DW_TAG_member = 0x0d,
+ DW_TAG_pointer_type = 0x0f,
+ DW_TAG_reference_type = 0x10,
+ DW_TAG_compile_unit = 0x11,
+ DW_TAG_string_type = 0x12,
+ DW_TAG_structure_type = 0x13,
+ DW_TAG_subroutine_type = 0x15,
+ DW_TAG_typedef = 0x16,
+ DW_TAG_union_type = 0x17,
+ DW_TAG_unspecified_parameters = 0x18,
+ DW_TAG_variant = 0x19,
+ DW_TAG_common_block = 0x1a,
+ DW_TAG_common_inclusion = 0x1b,
+ DW_TAG_inheritance = 0x1c,
+ DW_TAG_inlined_subroutine = 0x1d,
+ DW_TAG_module = 0x1e,
+ DW_TAG_ptr_to_member_type = 0x1f,
+ DW_TAG_set_type = 0x20,
+ DW_TAG_subrange_type = 0x21,
+ DW_TAG_with_stmt = 0x22,
+ DW_TAG_access_declaration = 0x23,
+ DW_TAG_base_type = 0x24,
+ DW_TAG_catch_block = 0x25,
+ DW_TAG_const_type = 0x26,
+ DW_TAG_constant = 0x27,
+ DW_TAG_enumerator = 0x28,
+ DW_TAG_file_type = 0x29,
+ DW_TAG_friend = 0x2a,
+ DW_TAG_namelist = 0x2b,
+ DW_TAG_namelist_item = 0x2c,
+ DW_TAG_packed_type = 0x2d,
+ DW_TAG_subprogram = 0x2e,
+ DW_TAG_template_type_parameter = 0x2f,
+ DW_TAG_template_value_parameter = 0x30,
+ DW_TAG_thrown_type = 0x31,
+ DW_TAG_try_block = 0x32,
+ DW_TAG_variant_part = 0x33,
+ DW_TAG_variable = 0x34,
+ DW_TAG_volatile_type = 0x35,
+ DW_TAG_dwarf_procedure = 0x36,
+ DW_TAG_restrict_type = 0x37,
+ DW_TAG_interface_type = 0x38,
+ DW_TAG_namespace = 0x39,
+ DW_TAG_imported_module = 0x3a,
+ DW_TAG_unspecified_type = 0x3b,
+ DW_TAG_partial_unit = 0x3c,
+ DW_TAG_imported_unit = 0x3d,
+ DW_TAG_condition = 0x3f,
+ DW_TAG_shared_type = 0x40,
+ DW_TAG_type_unit = 0x41,
+ DW_TAG_rvalue_reference_type = 0x42,
+ DW_TAG_template_alias = 0x43,
+#ifdef INCLUDE_DWARF5_VALUES
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ DW_TAG_coarray_type = 0x44,
+ DW_TAG_call_site = 0x45,
+ DW_TAG_call_site_parameter = 0x46,
+ DW_TAG_generic_subrange = 0x47,
+ DW_TAG_atomic_type = 0x48,
+ DW_TAG_dynamic_type = 0x49,
+ DW_TAG_aligned_type = 0x50,
+#endif
+ DW_TAG_lo_user = 0x4080,
+ DW_TAG_hi_user = 0xffff
+};
+
+enum Children : uint8_t {
+ DW_CHILDREN_no = 0x00,
+ DW_CHILDREN_yes = 0x01
+};
+
+enum Attribute {
+ DW_AT_sibling = 0x01,
+ DW_AT_location = 0x02,
+ DW_AT_name = 0x03,
+ DW_AT_ordering = 0x09,
+ DW_AT_byte_size = 0x0b,
+ DW_AT_bit_offset = 0x0c,
+ DW_AT_bit_size = 0x0d,
+ DW_AT_stmt_list = 0x10,
+ DW_AT_low_pc = 0x11,
+ DW_AT_high_pc = 0x12,
+ DW_AT_language = 0x13,
+ DW_AT_discr = 0x15,
+ DW_AT_discr_value = 0x16,
+ DW_AT_visibility = 0x17,
+ DW_AT_import = 0x18,
+ DW_AT_string_length = 0x19,
+ DW_AT_common_reference = 0x1a,
+ DW_AT_comp_dir = 0x1b,
+ DW_AT_const_value = 0x1c,
+ DW_AT_containing_type = 0x1d,
+ DW_AT_default_value = 0x1e,
+ DW_AT_inline = 0x20,
+ DW_AT_is_optional = 0x21,
+ DW_AT_lower_bound = 0x22,
+ DW_AT_producer = 0x25,
+ DW_AT_prototyped = 0x27,
+ DW_AT_return_addr = 0x2a,
+ DW_AT_start_scope = 0x2c,
+ DW_AT_bit_stride = 0x2e,
+ DW_AT_upper_bound = 0x2f,
+ DW_AT_abstract_origin = 0x31,
+ DW_AT_accessibility = 0x32,
+ DW_AT_address_class = 0x33,
+ DW_AT_artificial = 0x34,
+ DW_AT_base_types = 0x35,
+ DW_AT_calling_convention = 0x36,
+ DW_AT_count = 0x37,
+ DW_AT_data_member_location = 0x38,
+ DW_AT_decl_column = 0x39,
+ DW_AT_decl_file = 0x3a,
+ DW_AT_decl_line = 0x3b,
+ DW_AT_declaration = 0x3c,
+ DW_AT_discr_list = 0x3d,
+ DW_AT_encoding = 0x3e,
+ DW_AT_external = 0x3f,
+ DW_AT_frame_base = 0x40,
+ DW_AT_friend = 0x41,
+ DW_AT_identifier_case = 0x42,
+ DW_AT_macro_info = 0x43,
+ DW_AT_namelist_item = 0x44,
+ DW_AT_priority = 0x45,
+ DW_AT_segment = 0x46,
+ DW_AT_specification = 0x47,
+ DW_AT_static_link = 0x48,
+ DW_AT_type = 0x49,
+ DW_AT_use_location = 0x4a,
+ DW_AT_variable_parameter = 0x4b,
+ DW_AT_virtuality = 0x4c,
+ DW_AT_vtable_elem_location = 0x4d,
+ DW_AT_allocated = 0x4e,
+ DW_AT_associated = 0x4f,
+ DW_AT_data_location = 0x50,
+ DW_AT_byte_stride = 0x51,
+ DW_AT_entry_pc = 0x52,
+ DW_AT_use_UTF8 = 0x53,
+ DW_AT_extension = 0x54,
+ DW_AT_ranges = 0x55,
+ DW_AT_trampoline = 0x56,
+ DW_AT_call_column = 0x57,
+ DW_AT_call_file = 0x58,
+ DW_AT_call_line = 0x59,
+ DW_AT_description = 0x5a,
+ DW_AT_binary_scale = 0x5b,
+ DW_AT_decimal_scale = 0x5c,
+ DW_AT_small = 0x5d,
+ DW_AT_decimal_sign = 0x5e,
+ DW_AT_digit_count = 0x5f,
+ DW_AT_picture_string = 0x60,
+ DW_AT_mutable = 0x61,
+ DW_AT_threads_scaled = 0x62,
+ DW_AT_explicit = 0x63,
+ DW_AT_object_pointer = 0x64,
+ DW_AT_endianity = 0x65,
+ DW_AT_elemental = 0x66,
+ DW_AT_pure = 0x67,
+ DW_AT_recursive = 0x68,
+ DW_AT_signature = 0x69,
+ DW_AT_main_subprogram = 0x6a,
+ DW_AT_data_bit_offset = 0x6b,
+ DW_AT_const_expr = 0x6c,
+ DW_AT_enum_class = 0x6d,
+#ifdef INCLUDE_DWARF5_VALUES
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ DW_AT_linkage_name = 0x6e,
+ DW_AT_call_site_value = 0x6f,
+ DW_AT_call_site_data_value = 0x70,
+ DW_AT_call_site_target = 0x71,
+ DW_AT_call_site_target_clobbered = 0x72,
+ DW_AT_tail_call = 0x73,
+ DW_AT_all_tail_call_sites = 0x74,
+ DW_AT_all_call_sites = 0x75,
+ DW_AT_all_source_call_sites = 0x76,
+ DW_AT_call_site_parameter = 0x77,
+ DW_AT_tail_call = 0x78,
+ DW_AT_all_tail_call_sites = 0x79,
+ DW_AT_all_call_sites = 0x7a,
+ DW_AT_all_source_call_sites = 0x7b,
+ DW_AT_rank = 0x7c,
+ DW_AT_string_bitsize = 0x7d,
+ DW_AT_string_byte_size = 0x7e,
+ DW_AT_reference = 0x7f,
+ DW_AT_rvalue_reference = 0x80,
+ DW_AT_noreturn = 0x81,
+ DW_AT_alignment = 0x82,
+#endif
+ DW_AT_lo_user = 0x2000,
+ DW_AT_hi_user = 0xffff
+};
+
+enum Form : uint8_t {
+ DW_FORM_addr = 0x01,
+ DW_FORM_block2 = 0x03,
+ DW_FORM_block4 = 0x04,
+ DW_FORM_data2 = 0x05,
+ DW_FORM_data4 = 0x06,
+ DW_FORM_data8 = 0x07,
+ DW_FORM_string = 0x08,
+ DW_FORM_block = 0x09,
+ DW_FORM_block1 = 0x0a,
+ DW_FORM_data1 = 0x0b,
+ DW_FORM_flag = 0x0c,
+ DW_FORM_sdata = 0x0d,
+ DW_FORM_strp = 0x0e,
+ DW_FORM_udata = 0x0f,
+ DW_FORM_ref_addr = 0x10,
+ DW_FORM_ref1 = 0x11,
+ DW_FORM_ref2 = 0x12,
+ DW_FORM_ref4 = 0x13,
+ DW_FORM_ref8 = 0x14,
+ DW_FORM_ref_udata = 0x15,
+ DW_FORM_indirect = 0x16,
+ DW_FORM_sec_offset = 0x17,
+ DW_FORM_exprloc = 0x18,
+ DW_FORM_flag_present = 0x19,
+ DW_FORM_ref_sig8 = 0x20
+};
+
+enum Operation : uint16_t {
+ DW_OP_addr = 0x03,
+ DW_OP_deref = 0x06,
+ DW_OP_const1u = 0x08,
+ DW_OP_const1s = 0x09,
+ DW_OP_const2u = 0x0a,
+ DW_OP_const2s = 0x0b,
+ DW_OP_const4u = 0x0c,
+ DW_OP_const4s = 0x0d,
+ DW_OP_const8u = 0x0e,
+ DW_OP_const8s = 0x0f,
+ DW_OP_constu = 0x10,
+ DW_OP_consts = 0x11,
+ DW_OP_dup = 0x12,
+ DW_OP_drop = 0x13,
+ DW_OP_over = 0x14,
+ DW_OP_pick = 0x15,
+ DW_OP_swap = 0x16,
+ DW_OP_rot = 0x17,
+ DW_OP_xderef = 0x18,
+ DW_OP_abs = 0x19,
+ DW_OP_and = 0x1a,
+ DW_OP_div = 0x1b,
+ DW_OP_minus = 0x1c,
+ DW_OP_mod = 0x1d,
+ DW_OP_mul = 0x1e,
+ DW_OP_neg = 0x1f,
+ DW_OP_not = 0x20,
+ DW_OP_or = 0x21,
+ DW_OP_plus = 0x22,
+ DW_OP_plus_uconst = 0x23,
+ DW_OP_shl = 0x24,
+ DW_OP_shr = 0x25,
+ DW_OP_shra = 0x26,
+ DW_OP_xor = 0x27,
+ DW_OP_skip = 0x2f,
+ DW_OP_bra = 0x28,
+ DW_OP_eq = 0x29,
+ DW_OP_ge = 0x2a,
+ DW_OP_gt = 0x2b,
+ DW_OP_le = 0x2c,
+ DW_OP_lt = 0x2d,
+ DW_OP_ne = 0x2e,
+ DW_OP_lit0 = 0x30,
+ DW_OP_lit1 = 0x31,
+ DW_OP_lit2 = 0x32,
+ DW_OP_lit3 = 0x33,
+ DW_OP_lit4 = 0x34,
+ DW_OP_lit5 = 0x35,
+ DW_OP_lit6 = 0x36,
+ DW_OP_lit7 = 0x37,
+ DW_OP_lit8 = 0x38,
+ DW_OP_lit9 = 0x39,
+ DW_OP_lit10 = 0x3a,
+ DW_OP_lit11 = 0x3b,
+ DW_OP_lit12 = 0x3c,
+ DW_OP_lit13 = 0x3d,
+ DW_OP_lit14 = 0x3e,
+ DW_OP_lit15 = 0x3f,
+ DW_OP_lit16 = 0x40,
+ DW_OP_lit17 = 0x41,
+ DW_OP_lit18 = 0x42,
+ DW_OP_lit19 = 0x43,
+ DW_OP_lit20 = 0x44,
+ DW_OP_lit21 = 0x45,
+ DW_OP_lit22 = 0x46,
+ DW_OP_lit23 = 0x47,
+ DW_OP_lit24 = 0x48,
+ DW_OP_lit25 = 0x49,
+ DW_OP_lit26 = 0x4a,
+ DW_OP_lit27 = 0x4b,
+ DW_OP_lit28 = 0x4c,
+ DW_OP_lit29 = 0x4d,
+ DW_OP_lit30 = 0x4e,
+ DW_OP_lit31 = 0x4f,
+ DW_OP_reg0 = 0x50,
+ DW_OP_reg1 = 0x51,
+ DW_OP_reg2 = 0x52,
+ DW_OP_reg3 = 0x53,
+ DW_OP_reg4 = 0x54,
+ DW_OP_reg5 = 0x55,
+ DW_OP_reg6 = 0x56,
+ DW_OP_reg7 = 0x57,
+ DW_OP_reg8 = 0x58,
+ DW_OP_reg9 = 0x59,
+ DW_OP_reg10 = 0x5a,
+ DW_OP_reg11 = 0x5b,
+ DW_OP_reg12 = 0x5c,
+ DW_OP_reg13 = 0x5d,
+ DW_OP_reg14 = 0x5e,
+ DW_OP_reg15 = 0x5f,
+ DW_OP_reg16 = 0x60,
+ DW_OP_reg17 = 0x61,
+ DW_OP_reg18 = 0x62,
+ DW_OP_reg19 = 0x63,
+ DW_OP_reg20 = 0x64,
+ DW_OP_reg21 = 0x65,
+ DW_OP_reg22 = 0x66,
+ DW_OP_reg23 = 0x67,
+ DW_OP_reg24 = 0x68,
+ DW_OP_reg25 = 0x69,
+ DW_OP_reg26 = 0x6a,
+ DW_OP_reg27 = 0x6b,
+ DW_OP_reg28 = 0x6c,
+ DW_OP_reg29 = 0x6d,
+ DW_OP_reg30 = 0x6e,
+ DW_OP_reg31 = 0x6f,
+ DW_OP_breg0 = 0x50,
+ DW_OP_breg1 = 0x51,
+ DW_OP_breg2 = 0x52,
+ DW_OP_breg3 = 0x53,
+ DW_OP_breg4 = 0x54,
+ DW_OP_breg5 = 0x55,
+ DW_OP_breg6 = 0x56,
+ DW_OP_breg7 = 0x57,
+ DW_OP_breg8 = 0x58,
+ DW_OP_breg9 = 0x59,
+ DW_OP_breg10 = 0x5a,
+ DW_OP_breg11 = 0x5b,
+ DW_OP_breg12 = 0x5c,
+ DW_OP_breg13 = 0x5d,
+ DW_OP_breg14 = 0x5e,
+ DW_OP_breg15 = 0x5f,
+ DW_OP_breg16 = 0x60,
+ DW_OP_breg17 = 0x61,
+ DW_OP_breg18 = 0x62,
+ DW_OP_breg19 = 0x63,
+ DW_OP_breg20 = 0x64,
+ DW_OP_breg21 = 0x65,
+ DW_OP_breg22 = 0x66,
+ DW_OP_breg23 = 0x67,
+ DW_OP_breg24 = 0x68,
+ DW_OP_breg25 = 0x69,
+ DW_OP_breg26 = 0x6a,
+ DW_OP_breg27 = 0x6b,
+ DW_OP_breg28 = 0x6c,
+ DW_OP_breg29 = 0x6d,
+ DW_OP_breg30 = 0x6e,
+ DW_OP_breg31 = 0x6f,
+ DW_OP_regx = 0x90,
+ DW_OP_fbreg = 0x91,
+ DW_OP_bregx = 0x92,
+ DW_OP_piece = 0x93,
+ DW_OP_deref_size = 0x94,
+ DW_OP_xderef_size = 0x95,
+ DW_OP_nop = 0x96,
+ DW_OP_push_object_address = 0x97,
+ DW_OP_call2 = 0x98,
+ DW_OP_call4 = 0x99,
+ DW_OP_call_ref = 0x9a,
+ DW_OP_form_tls_address = 0x9b,
+ DW_OP_call_frame_cfa = 0x9c,
+ DW_OP_bit_piece = 0x9d,
+ DW_OP_implicit_value = 0x9e,
+ DW_OP_stack_value = 0x9f,
+#ifdef INCLUDE_DWARF5_VALUES
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ DW_OP_entry_value = 0xa0,
+ DW_OP_const_type = 0xa1,
+ DW_OP_regval_type = 0xa2,
+ DW_OP_deref_type = 0xa3,
+ DW_OP_xderef_type = 0xa4,
+ DW_OP_convert = 0xa5,
+ DW_OP_reinterpret = 0xa6,
+#endif
+ DW_OP_lo_user = 0xe0,
+ DW_OP_hi_user = 0xff
+};
+
+enum BaseTypeEncoding : uint8_t {
+ DW_ATE_address = 0x01,
+ DW_ATE_boolean = 0x02,
+ DW_ATE_complex_float = 0x03,
+ DW_ATE_float = 0x04,
+ DW_ATE_signed = 0x05,
+ DW_ATE_signed_char = 0x06,
+ DW_ATE_unsigned = 0x07,
+ DW_ATE_unsigned_char = 0x08,
+ DW_ATE_imaginary_float = 0x09,
+ DW_ATE_packed_decimal = 0x0a,
+ DW_ATE_numeric_string = 0x0b,
+ DW_ATE_edited = 0x0c,
+ DW_ATE_signed_fixed = 0x0d,
+ DW_ATE_unsigned_fixed = 0x0e,
+ DW_ATE_decimal_float = 0x0f,
+ DW_ATE_UTF = 0x10,
+ DW_ATE_lo_user = 0x80,
+ DW_ATE_hi_user = 0xff
+};
+
+enum DecimalSign : uint8_t {
+ DW_DS_unsigned = 0x01,
+ DW_DS_leading_overpunch = 0x02,
+ DW_DS_trailing_overpunch = 0x03,
+ DW_DS_leading_separate = 0x04,
+ DW_DS_trailing_separate = 0x05
+};
+
+enum Endianity : uint8_t {
+ DW_END_default = 0x00,
+ DW_END_big = 0x01,
+ DW_END_little = 0x02,
+ DW_END_lo_user = 0x40,
+ DW_END_hi_user = 0xff
+};
+
+enum Accessibility : uint8_t {
+ DW_ACCESS_public = 0x01,
+ DW_ACCESS_protected = 0x02,
+ DW_ACCESS_private = 0x03
+};
+
+enum Visibility : uint8_t {
+ DW_VIS_local = 0x01,
+ DW_VIS_exported = 0x02,
+ DW_VIS_qualified = 0x03
+};
+
+enum Virtuality : uint8_t {
+ DW_VIRTUALITY_none = 0x00,
+ DW_VIRTUALITY_virtual = 0x01,
+ DW_VIRTUALITY_pure_virtual = 0x02
+};
+
+enum Language {
+ DW_LANG_C89 = 0x01,
+ DW_LANG_C = 0x02,
+ DW_LANG_Ada83 = 0x03,
+ DW_LANG_C_plus_plus = 0x04,
+ DW_LANG_Cobol74 = 0x05,
+ DW_LANG_Cobol85 = 0x06,
+ DW_LANG_Fortran77 = 0x07,
+ DW_LANG_Fortran90 = 0x08,
+ DW_LANG_Pascal83 = 0x09,
+ DW_LANG_Modula2 = 0x0a,
+ DW_LANG_Java = 0x0b,
+ DW_LANG_C99 = 0x0c,
+ DW_LANG_Ada95 = 0x0d,
+ DW_LANG_Fortran95 = 0x0e,
+ DW_LANG_PLI = 0x0f,
+ DW_LANG_ObjC = 0x10,
+ DW_LANG_ObjC_plus_plus = 0x11,
+ DW_LANG_UPC = 0x12,
+ DW_LANG_D = 0x13,
+ DW_LANG_Python = 0x14,
+#ifdef INCLUDE_DWARF5_VALUES
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ DW_LANG_OpenCL = 0x15,
+ DW_LANG_Go = 0x16,
+ DW_LANG_Modula3 = 0x17,
+ DW_LANG_Haskell = 0x18,
+ DW_LANG_C_plus_plus_03 = 0x19,
+ DW_LANG_C_plus_plus_11 = 0x1a,
+ DW_LANG_OCaml = 0x1b,
+ DW_LANG_Rust = 0x1c,
+ DW_LANG_C11 = 0x1d,
+ DW_LANG_Swift = 0x1e,
+ DW_LANG_Julia = 0x1f,
+#endif
+ DW_LANG_lo_user = 0x8000,
+ DW_LANG_hi_user = 0xffff
+};
+
+enum Identifier : uint8_t {
+ DW_ID_case_sensitive = 0x00,
+ DW_ID_up_case = 0x01,
+ DW_ID_down_case = 0x02,
+ DW_ID_case_insensitive = 0x03
+};
+
+enum CallingConvention : uint8_t {
+ DW_CC_normal = 0x01,
+ DW_CC_program = 0x02,
+ DW_CC_nocall = 0x03,
+ DW_CC_lo_user = 0x40,
+ DW_CC_hi_user = 0xff
+};
+
+enum Inline : uint8_t {
+ DW_INL_not_inlined = 0x00,
+ DW_INL_inlined = 0x01,
+ DW_INL_declared_not_inlined = 0x02,
+ DW_INL_declared_inlined = 0x03
+};
+
+enum ArrayOrdering : uint8_t {
+ DW_ORD_row_major = 0x00,
+ DW_ORD_col_major = 0x01
+};
+
+enum DiscriminantList : uint8_t {
+ DW_DSC_label = 0x00,
+ DW_DSC_range = 0x01
+};
+
+enum LineNumberOpcode : uint8_t {
+ DW_LNS_copy = 0x01,
+ DW_LNS_advance_pc = 0x02,
+ DW_LNS_advance_line = 0x03,
+ DW_LNS_set_file = 0x04,
+ DW_LNS_set_column = 0x05,
+ DW_LNS_negate_stmt = 0x06,
+ DW_LNS_set_basic_block = 0x07,
+ DW_LNS_const_add_pc = 0x08,
+ DW_LNS_fixed_advance_pc = 0x09,
+ DW_LNS_set_prologue_end = 0x0a,
+ DW_LNS_set_epilogue_begin = 0x0b,
+ DW_LNS_set_isa = 0x0c
+};
+
+enum LineNumberExtendedOpcode : uint8_t {
+ DW_LNE_end_sequence = 0x01,
+ DW_LNE_set_address = 0x02,
+ DW_LNE_define_file = 0x03,
+ DW_LNE_set_discriminator = 0x04,
+ DW_LNE_lo_user = 0x80,
+ DW_LNE_hi_user = 0xff
+};
+
+#ifdef INCLUDE_DWARF5_VALUES
+enum LineNumberFormat : uint8_t {
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ //
+ DW_LNF_path = 0x1,
+ DW_LNF_include_index = 0x2,
+ DW_LNF_timestamp = 0x3,
+ DW_LNF_size = 0x4,
+ DW_LNF_MD5 = 0x5,
+ DW_LNF_lo_user = 0x2000,
+ DW_LNF_hi_user = 0x3fff
+};
+#endif
+
+enum MacroInfo : uint8_t {
+ DW_MACINFO_define = 0x01,
+ DW_MACINFO_undef = 0x02,
+ DW_MACINFO_start_file = 0x03,
+ DW_MACINFO_end_file = 0x04,
+ DW_MACINFO_vendor_ext = 0xff
+};
+
+#ifdef INCLUDE_DWARF5_VALUES
+enum Macro : uint8_t {
+ // Values to be added in Dwarf 5. Final value not yet specified. Values listed
+ // may be different than other implementations. Use with caution.
+ // TODO Update these values when Dwarf 5 is released.
+ DW_MACRO_define = 0x01,
+ DW_MACRO_undef = 0x02,
+ DW_MACRO_start_file = 0x03,
+ DW_MACRO_end_file = 0x04,
+ DW_MACRO_define_indirect = 0x05,
+ DW_MACRO_undef_indirect = 0x06,
+ DW_MACRO_transparent_include = 0x07,
+ DW_MACRO_define_indirectx = 0x0b,
+ DW_MACRO_undef_indirectx = 0x0c,
+ DW_MACRO_lo_user = 0xe0,
+ DW_MACRO_hi_user = 0xff
+};
+#endif
+
+const uint32_t CIE_ID_32 = 0xffffffff;
+const uint64_t CIE_ID_64 = 0xffffffffffffffff;
+
+enum CallFrameInstruction : uint8_t {
+ DW_CFA_advance_loc = 0x40,
+ DW_CFA_offset = 0x80,
+ DW_CFA_restore = 0xc0,
+ DW_CFA_nop = 0x00,
+ DW_CFA_set_loc = 0x01,
+ DW_CFA_advance_loc1 = 0x02,
+ DW_CFA_advance_loc2 = 0x03,
+ DW_CFA_advance_loc4 = 0x04,
+ DW_CFA_offset_extended = 0x05,
+ DW_CFA_restore_extended = 0x06,
+ DW_CFA_undefined = 0x07,
+ DW_CFA_same_value = 0x08,
+ DW_CFA_register = 0x09,
+ DW_CFA_remember_state = 0x0a,
+ DW_CFA_restore_state = 0x0b,
+ DW_CFA_def_cfa = 0x0c,
+ DW_CFA_def_cfa_register = 0x0d,
+ DW_CFA_def_cfa_offset = 0x0e,
+ DW_CFA_def_cfa_expression = 0x0f,
+ DW_CFA_expression = 0x10,
+ DW_CFA_offset_extended_sf = 0x11,
+ DW_CFA_def_cfa_sf = 0x12,
+ DW_CFA_def_cfa_offset_sf = 0x13,
+ DW_CFA_val_offset = 0x14,
+ DW_CFA_val_offset_sf = 0x15,
+ DW_CFA_val_expression = 0x16,
+ DW_CFA_lo_user = 0x1c,
+ DW_CFA_hi_user = 0x3f
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_DWARF_H_
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 0df8211..bb33978 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -22,6 +22,8 @@
#include "base/logging.h"
#include "base/stringprintf.h"
#include "base/stl_util.h"
+#include "dwarf.h"
+#include "leb128.h"
#include "utils.h"
#include "instruction_set.h"
@@ -108,43 +110,51 @@ ElfFile::ElfFile(File* file, bool writable, bool program_header_only)
: file_(file),
writable_(writable),
program_header_only_(program_header_only),
- header_(NULL),
- base_address_(NULL),
- program_headers_start_(NULL),
- section_headers_start_(NULL),
- dynamic_program_header_(NULL),
- dynamic_section_start_(NULL),
- symtab_section_start_(NULL),
- dynsym_section_start_(NULL),
- strtab_section_start_(NULL),
- dynstr_section_start_(NULL),
- hash_section_start_(NULL),
- symtab_symbol_table_(NULL),
- dynsym_symbol_table_(NULL),
- jit_elf_image_(NULL),
- jit_gdb_entry_(NULL) {
- CHECK(file != NULL);
+ header_(nullptr),
+ base_address_(nullptr),
+ program_headers_start_(nullptr),
+ section_headers_start_(nullptr),
+ dynamic_program_header_(nullptr),
+ dynamic_section_start_(nullptr),
+ symtab_section_start_(nullptr),
+ dynsym_section_start_(nullptr),
+ strtab_section_start_(nullptr),
+ dynstr_section_start_(nullptr),
+ hash_section_start_(nullptr),
+ symtab_symbol_table_(nullptr),
+ dynsym_symbol_table_(nullptr),
+ jit_elf_image_(nullptr),
+ jit_gdb_entry_(nullptr) {
+ CHECK(file != nullptr);
}
ElfFile* ElfFile::Open(File* file, bool writable, bool program_header_only,
std::string* error_msg) {
std::unique_ptr<ElfFile> elf_file(new ElfFile(file, writable, program_header_only));
- if (!elf_file->Setup(error_msg)) {
- return nullptr;
- }
- return elf_file.release();
-}
-
-bool ElfFile::Setup(std::string* error_msg) {
int prot;
int flags;
- if (writable_) {
+ if (writable) {
prot = PROT_READ | PROT_WRITE;
flags = MAP_SHARED;
} else {
prot = PROT_READ;
flags = MAP_PRIVATE;
}
+ if (!elf_file->Setup(prot, flags, error_msg)) {
+ return nullptr;
+ }
+ return elf_file.release();
+}
+
+ElfFile* ElfFile::Open(File* file, int prot, int flags, std::string* error_msg) {
+ std::unique_ptr<ElfFile> elf_file(new ElfFile(file, (prot & PROT_WRITE) == PROT_WRITE, false));
+ if (!elf_file->Setup(prot, flags, error_msg)) {
+ return nullptr;
+ }
+ return elf_file.release();
+}
+
+bool ElfFile::Setup(int prot, int flags, std::string* error_msg) {
int64_t temp_file_length = file_->GetLength();
if (temp_file_length < 0) {
errno = -temp_file_length;
@@ -201,7 +211,7 @@ bool ElfFile::Setup(std::string* error_msg) {
// Find .dynamic section info from program header
dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC);
- if (dynamic_program_header_ == NULL) {
+ if (dynamic_program_header_ == nullptr) {
*error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
file_->GetPath().c_str());
return false;
@@ -263,14 +273,14 @@ ElfFile::~ElfFile() {
}
bool ElfFile::SetMap(MemMap* map, std::string* error_msg) {
- if (map == NULL) {
+ if (map == nullptr) {
// MemMap::Open should have already set an error.
DCHECK(!error_msg->empty());
return false;
}
map_.reset(map);
- CHECK(map_.get() != NULL) << file_->GetPath();
- CHECK(map_->Begin() != NULL) << file_->GetPath();
+ CHECK(map_.get() != nullptr) << file_->GetPath();
+ CHECK(map_->Begin() != nullptr) << file_->GetPath();
header_ = reinterpret_cast<Elf32_Ehdr*>(map_->Begin());
if ((ELFMAG0 != header_->e_ident[EI_MAG0])
@@ -397,27 +407,27 @@ bool ElfFile::SetMap(MemMap* map, std::string* error_msg) {
Elf32_Ehdr& ElfFile::GetHeader() const {
- CHECK(header_ != NULL);
+ CHECK(header_ != nullptr);
return *header_;
}
byte* ElfFile::GetProgramHeadersStart() const {
- CHECK(program_headers_start_ != NULL);
+ CHECK(program_headers_start_ != nullptr);
return program_headers_start_;
}
byte* ElfFile::GetSectionHeadersStart() const {
- CHECK(section_headers_start_ != NULL);
+ CHECK(section_headers_start_ != nullptr);
return section_headers_start_;
}
Elf32_Phdr& ElfFile::GetDynamicProgramHeader() const {
- CHECK(dynamic_program_header_ != NULL);
+ CHECK(dynamic_program_header_ != nullptr);
return *dynamic_program_header_;
}
Elf32_Dyn* ElfFile::GetDynamicSectionStart() const {
- CHECK(dynamic_section_start_ != NULL);
+ CHECK(dynamic_section_start_ != nullptr);
return dynamic_section_start_;
}
@@ -435,10 +445,10 @@ Elf32_Sym* ElfFile::GetSymbolSectionStart(Elf32_Word section_type) const {
}
default: {
LOG(FATAL) << section_type;
- symbol_section_start = NULL;
+ symbol_section_start = nullptr;
}
}
- CHECK(symbol_section_start != NULL);
+ CHECK(symbol_section_start != nullptr);
return symbol_section_start;
}
@@ -456,17 +466,17 @@ const char* ElfFile::GetStringSectionStart(Elf32_Word section_type) const {
}
default: {
LOG(FATAL) << section_type;
- string_section_start = NULL;
+ string_section_start = nullptr;
}
}
- CHECK(string_section_start != NULL);
+ CHECK(string_section_start != nullptr);
return string_section_start;
}
const char* ElfFile::GetString(Elf32_Word section_type, Elf32_Word i) const {
CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
if (i == 0) {
- return NULL;
+ return nullptr;
}
const char* string_section_start = GetStringSectionStart(section_type);
const char* string = string_section_start + i;
@@ -474,7 +484,7 @@ const char* ElfFile::GetString(Elf32_Word section_type, Elf32_Word i) const {
}
Elf32_Word* ElfFile::GetHashSectionStart() const {
- CHECK(hash_section_start_ != NULL);
+ CHECK(hash_section_start_ != nullptr);
return hash_section_start_;
}
@@ -516,7 +526,7 @@ Elf32_Phdr* ElfFile::FindProgamHeaderByType(Elf32_Word type) const {
return &program_header;
}
}
- return NULL;
+ return nullptr;
}
Elf32_Word ElfFile::GetSectionHeaderNum() const {
@@ -543,7 +553,7 @@ Elf32_Shdr* ElfFile::FindSectionByType(Elf32_Word type) const {
return &section_header;
}
}
- return NULL;
+ return nullptr;
}
// from bionic
@@ -565,6 +575,15 @@ Elf32_Shdr& ElfFile::GetSectionNameStringSection() const {
}
const byte* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
+ const Elf32_Sym* sym = FindDynamicSymbol(symbol_name);
+ if (sym != nullptr) {
+ return base_address_ + sym->st_value;
+ } else {
+ return nullptr;
+ }
+}
+
+const Elf32_Sym* ElfFile::FindDynamicSymbol(const std::string& symbol_name) const {
Elf32_Word hash = elfhash(symbol_name.c_str());
Elf32_Word bucket_index = hash % GetHashBucketNum();
Elf32_Word symbol_and_chain_index = GetHashBucket(bucket_index);
@@ -572,11 +591,11 @@ const byte* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) co
Elf32_Sym& symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
const char* name = GetString(SHT_DYNSYM, symbol.st_name);
if (symbol_name == name) {
- return base_address_ + symbol.st_value;
+ return &symbol;
}
symbol_and_chain_index = GetHashChain(symbol_and_chain_index);
}
- return NULL;
+ return nullptr;
}
bool ElfFile::IsSymbolSectionType(Elf32_Word section_type) {
@@ -606,7 +625,7 @@ ElfFile::SymbolTable** ElfFile::GetSymbolTable(Elf32_Word section_type) {
}
default: {
LOG(FATAL) << section_type;
- return NULL;
+ return nullptr;
}
}
}
@@ -618,12 +637,12 @@ Elf32_Sym* ElfFile::FindSymbolByName(Elf32_Word section_type,
CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
SymbolTable** symbol_table = GetSymbolTable(section_type);
- if (*symbol_table != NULL || build_map) {
- if (*symbol_table == NULL) {
+ if (*symbol_table != nullptr || build_map) {
+ if (*symbol_table == nullptr) {
DCHECK(build_map);
*symbol_table = new SymbolTable;
Elf32_Shdr* symbol_section = FindSectionByType(section_type);
- CHECK(symbol_section != NULL) << file_->GetPath();
+ CHECK(symbol_section != nullptr) << file_->GetPath();
Elf32_Shdr& string_section = GetSectionHeader(symbol_section->sh_link);
for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Elf32_Sym& symbol = GetSymbol(section_type, i);
@@ -632,7 +651,7 @@ Elf32_Sym* ElfFile::FindSymbolByName(Elf32_Word section_type,
continue;
}
const char* name = GetString(string_section, symbol.st_name);
- if (name == NULL) {
+ if (name == nullptr) {
continue;
}
std::pair<SymbolTable::iterator, bool> result =
@@ -647,36 +666,36 @@ Elf32_Sym* ElfFile::FindSymbolByName(Elf32_Word section_type,
}
}
}
- CHECK(*symbol_table != NULL);
+ CHECK(*symbol_table != nullptr);
SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
if (it == (*symbol_table)->end()) {
- return NULL;
+ return nullptr;
}
return it->second;
}
// Fall back to linear search
Elf32_Shdr* symbol_section = FindSectionByType(section_type);
- CHECK(symbol_section != NULL) << file_->GetPath();
+ CHECK(symbol_section != nullptr) << file_->GetPath();
Elf32_Shdr& string_section = GetSectionHeader(symbol_section->sh_link);
for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Elf32_Sym& symbol = GetSymbol(section_type, i);
const char* name = GetString(string_section, symbol.st_name);
- if (name == NULL) {
+ if (name == nullptr) {
continue;
}
if (symbol_name == name) {
return &symbol;
}
}
- return NULL;
+ return nullptr;
}
Elf32_Addr ElfFile::FindSymbolAddress(Elf32_Word section_type,
const std::string& symbol_name,
bool build_map) {
Elf32_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
- if (symbol == NULL) {
+ if (symbol == nullptr) {
return 0;
}
return symbol->st_value;
@@ -688,7 +707,7 @@ const char* ElfFile::GetString(Elf32_Shdr& string_section, Elf32_Word i) const {
CHECK_EQ(static_cast<Elf32_Word>(SHT_STRTAB), string_section.sh_type) << file_->GetPath();
CHECK_LT(i, string_section.sh_size) << file_->GetPath();
if (i == 0) {
- return NULL;
+ return nullptr;
}
byte* strings = Begin() + string_section.sh_offset;
byte* string = strings + i;
@@ -846,7 +865,7 @@ bool ElfFile::Load(bool executable, std::string* error_msg) {
std::string reservation_name("ElfFile reservation for ");
reservation_name += file_->GetPath();
std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
- NULL, GetLoadedSize(), PROT_NONE, false,
+ nullptr, GetLoadedSize(), PROT_NONE, false,
error_msg));
if (reserve.get() == nullptr) {
*error_msg = StringPrintf("Failed to allocate %s: %s",
@@ -970,29 +989,323 @@ bool ElfFile::ValidPointer(const byte* start) const {
return false;
}
-static bool check_section_name(ElfFile& file, int section_num, const char *name) {
- Elf32_Shdr& section_header = file.GetSectionHeader(section_num);
- const char *section_name = file.GetString(SHT_SYMTAB, section_header.sh_name);
- return strcmp(name, section_name) == 0;
+
+Elf32_Shdr* ElfFile::FindSectionByName(const std::string& name) const {
+ CHECK(!program_header_only_);
+ Elf32_Shdr& shstrtab_sec = GetSectionNameStringSection();
+ for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) {
+ Elf32_Shdr& shdr = GetSectionHeader(i);
+ const char* sec_name = GetString(shstrtab_sec, shdr.sh_name);
+ if (sec_name == nullptr) {
+ continue;
+ }
+ if (name == sec_name) {
+ return &shdr;
+ }
+ }
+ return nullptr;
}
-static void IncrementUint32(byte *p, uint32_t increment) {
- uint32_t *u = reinterpret_cast<uint32_t *>(p);
- *u += increment;
+struct PACKED(1) FDE {
+ uint32_t raw_length_;
+ uint32_t GetLength() {
+ return raw_length_ + sizeof(raw_length_);
+ }
+ uint32_t CIE_pointer;
+ uint32_t initial_location;
+ uint32_t address_range;
+ uint8_t instructions[0];
+};
+
+static FDE* NextFDE(FDE* frame) {
+ byte* fde_bytes = reinterpret_cast<byte*>(frame);
+ fde_bytes += frame->GetLength();
+ return reinterpret_cast<FDE*>(fde_bytes);
}
-static void RoundAndClear(byte *image, uint32_t& offset, int pwr2) {
- uint32_t mask = pwr2 - 1;
- while (offset & mask) {
- image[offset++] = 0;
+static bool IsFDE(FDE* frame) {
+ // TODO This seems to be the constant everyone uses (for the .debug_frame
+ // section at least), however we should investigate this further.
+ const uint32_t kDwarfCIE_id = 0xffffffff;
+ const uint32_t kReservedLengths[] = {0xffffffff, 0xfffffff0};
+ return frame->CIE_pointer != kDwarfCIE_id &&
+ frame->raw_length_ != kReservedLengths[0] && frame->raw_length_ != kReservedLengths[1];
+}
+
+// TODO This only works for 32-bit Elf Files.
+static bool FixupDebugFrame(uintptr_t text_start, byte* dbg_frame, size_t dbg_frame_size) {
+ FDE* last_frame = reinterpret_cast<FDE*>(dbg_frame + dbg_frame_size);
+ FDE* frame = NextFDE(reinterpret_cast<FDE*>(dbg_frame));
+ for (; frame < last_frame; frame = NextFDE(frame)) {
+ if (!IsFDE(frame)) {
+ return false;
+ }
+ frame->initial_location += text_start;
}
+ return true;
}
-// Simple macro to bump a point to a section header to the next one.
-#define BUMP_SHENT(sp) \
- sp = reinterpret_cast<Elf32_Shdr *> (\
- reinterpret_cast<byte*>(sp) + elf_hdr.e_shentsize);\
- offset += elf_hdr.e_shentsize
+struct PACKED(1) DebugInfoHeader {
+ uint32_t unit_length; // TODO 32-bit specific size
+ uint16_t version;
+ uint32_t debug_abbrev_offset; // TODO 32-bit specific size
+ uint8_t address_size;
+};
+
+// Returns -1 if it is variable length, which we will just disallow for now.
+static int32_t FormLength(uint32_t att) {
+ switch (att) {
+ case DW_FORM_data1:
+ case DW_FORM_flag:
+ case DW_FORM_flag_present:
+ case DW_FORM_ref1:
+ return 1;
+
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ return 2;
+
+ case DW_FORM_addr: // TODO 32-bit only
+ case DW_FORM_ref_addr: // TODO 32-bit only
+ case DW_FORM_sec_offset: // TODO 32-bit only
+ case DW_FORM_strp: // TODO 32-bit only
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ return 4;
+
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
+ return 8;
+
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ case DW_FORM_exprloc:
+ case DW_FORM_indirect:
+ case DW_FORM_ref_udata:
+ case DW_FORM_sdata:
+ case DW_FORM_string:
+ case DW_FORM_udata:
+ default:
+ return -1;
+ }
+}
+
+class DebugTag {
+ public:
+ const uint32_t index_;
+ ~DebugTag() {}
+ // Creates a new tag and moves data pointer up to the start of the next one.
+ // nullptr means error.
+ static DebugTag* Create(const byte** data_pointer) {
+ const byte* data = *data_pointer;
+ uint32_t index = DecodeUnsignedLeb128(&data);
+ std::unique_ptr<DebugTag> tag(new DebugTag(index));
+ tag->size_ = static_cast<uint32_t>(
+ reinterpret_cast<uintptr_t>(data) - reinterpret_cast<uintptr_t>(*data_pointer));
+ // skip the abbrev
+ tag->tag_ = DecodeUnsignedLeb128(&data);
+ tag->has_child_ = (*data == 0);
+ data++;
+ while (true) {
+ uint32_t attr = DecodeUnsignedLeb128(&data);
+ uint32_t form = DecodeUnsignedLeb128(&data);
+ if (attr == 0 && form == 0) {
+ break;
+ } else if (attr == 0 || form == 0) {
+ // Bad abbrev.
+ return nullptr;
+ }
+ int32_t size = FormLength(form);
+ if (size == -1) {
+ return nullptr;
+ }
+ tag->AddAttribute(attr, static_cast<uint32_t>(size));
+ }
+ *data_pointer = data;
+ return tag.release();
+ }
+
+ uint32_t GetSize() const {
+ return size_;
+ }
+
+ bool HasChild() {
+ return has_child_;
+ }
+
+ uint32_t GetTagNumber() {
+ return tag_;
+ }
+
+ // Gets the offset of a particular attribute in this tag structure.
+ // Interpretation of the data is left to the consumer. 0 is returned if the
+ // tag does not contain the attribute.
+ uint32_t GetOffsetOf(uint32_t dwarf_attribute) const {
+ auto it = off_map_.find(dwarf_attribute);
+ if (it == off_map_.end()) {
+ return 0;
+ } else {
+ return it->second;
+ }
+ }
+
+ // Gets the size of attribute
+ uint32_t GetAttrSize(uint32_t dwarf_attribute) const {
+ auto it = size_map_.find(dwarf_attribute);
+ if (it == size_map_.end()) {
+ return 0;
+ } else {
+ return it->second;
+ }
+ }
+
+ private:
+ explicit DebugTag(uint32_t index) : index_(index) {}
+ void AddAttribute(uint32_t type, uint32_t attr_size) {
+ off_map_.insert(std::pair<uint32_t, uint32_t>(type, size_));
+ size_map_.insert(std::pair<uint32_t, uint32_t>(type, attr_size));
+ size_ += attr_size;
+ }
+ std::map<uint32_t, uint32_t> off_map_;
+ std::map<uint32_t, uint32_t> size_map_;
+ uint32_t size_;
+ uint32_t tag_;
+ bool has_child_;
+};
+
+class DebugAbbrev {
+ public:
+ ~DebugAbbrev() {}
+ static DebugAbbrev* Create(const byte* dbg_abbrev, size_t dbg_abbrev_size) {
+ std::unique_ptr<DebugAbbrev> abbrev(new DebugAbbrev);
+ const byte* last = dbg_abbrev + dbg_abbrev_size;
+ while (dbg_abbrev < last) {
+ std::unique_ptr<DebugTag> tag(DebugTag::Create(&dbg_abbrev));
+ if (tag.get() == nullptr) {
+ return nullptr;
+ } else {
+ abbrev->tags_.insert(std::pair<uint32_t, uint32_t>(tag->index_, abbrev->tag_list_.size()));
+ abbrev->tag_list_.push_back(std::move(tag));
+ }
+ }
+ return abbrev.release();
+ }
+
+ DebugTag* ReadTag(const byte* entry) {
+ uint32_t tag_num = DecodeUnsignedLeb128(&entry);
+ auto it = tags_.find(tag_num);
+ if (it == tags_.end()) {
+ return nullptr;
+ } else {
+ CHECK_GT(tag_list_.size(), it->second);
+ return tag_list_.at(it->second).get();
+ }
+ }
+
+ private:
+ DebugAbbrev() {}
+ std::map<uint32_t, uint32_t> tags_;
+ std::vector<std::unique_ptr<DebugTag>> tag_list_;
+};
+
+class DebugInfoIterator {
+ public:
+ static DebugInfoIterator* Create(DebugInfoHeader* header, size_t frame_size,
+ DebugAbbrev* abbrev) {
+ std::unique_ptr<DebugInfoIterator> iter(new DebugInfoIterator(header, frame_size, abbrev));
+ if (iter->GetCurrentTag() == nullptr) {
+ return nullptr;
+ } else {
+ return iter.release();
+ }
+ }
+ ~DebugInfoIterator() {}
+
+ // Moves to the next DIE. Returns false if at last entry.
+ // TODO Handle variable length attributes.
+ bool next() {
+ if (current_entry_ == nullptr || current_tag_ == nullptr) {
+ return false;
+ }
+ current_entry_ += current_tag_->GetSize();
+ if (current_entry_ >= last_entry_) {
+ current_entry_ = nullptr;
+ return false;
+ }
+ current_tag_ = abbrev_->ReadTag(current_entry_);
+ if (current_tag_ == nullptr) {
+ current_entry_ = nullptr;
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ const DebugTag* GetCurrentTag() {
+ return const_cast<DebugTag*>(current_tag_);
+ }
+ byte* GetPointerToField(uint8_t dwarf_field) {
+ if (current_tag_ == nullptr || current_entry_ == nullptr || current_entry_ >= last_entry_) {
+ return nullptr;
+ }
+ uint32_t off = current_tag_->GetOffsetOf(dwarf_field);
+ if (off == 0) {
+ // tag does not have that field.
+ return nullptr;
+ } else {
+ DCHECK_LT(off, current_tag_->GetSize());
+ return current_entry_ + off;
+ }
+ }
+
+ private:
+ DebugInfoIterator(DebugInfoHeader* header, size_t frame_size, DebugAbbrev* abbrev)
+ : abbrev_(abbrev),
+ last_entry_(reinterpret_cast<byte*>(header) + frame_size),
+ current_entry_(reinterpret_cast<byte*>(header) + sizeof(DebugInfoHeader)),
+ current_tag_(abbrev_->ReadTag(current_entry_)) {}
+ DebugAbbrev* abbrev_;
+ byte* last_entry_;
+ byte* current_entry_;
+ DebugTag* current_tag_;
+};
+
+static bool FixupDebugInfo(uint32_t text_start, DebugInfoIterator* iter) {
+ do {
+ if (iter->GetCurrentTag()->GetAttrSize(DW_AT_low_pc) != sizeof(int32_t) ||
+ iter->GetCurrentTag()->GetAttrSize(DW_AT_high_pc) != sizeof(int32_t)) {
+ return false;
+ }
+ uint32_t* PC_low = reinterpret_cast<uint32_t*>(iter->GetPointerToField(DW_AT_low_pc));
+ uint32_t* PC_high = reinterpret_cast<uint32_t*>(iter->GetPointerToField(DW_AT_high_pc));
+ if (PC_low != nullptr && PC_high != nullptr) {
+ *PC_low += text_start;
+ *PC_high += text_start;
+ }
+ } while (iter->next());
+ return true;
+}
+
+static bool FixupDebugSections(const byte* dbg_abbrev, size_t dbg_abbrev_size,
+ uintptr_t text_start,
+ byte* dbg_info, size_t dbg_info_size,
+ byte* dbg_frame, size_t dbg_frame_size) {
+ std::unique_ptr<DebugAbbrev> abbrev(DebugAbbrev::Create(dbg_abbrev, dbg_abbrev_size));
+ if (abbrev.get() == nullptr) {
+ return false;
+ }
+ std::unique_ptr<DebugInfoIterator> iter(
+ DebugInfoIterator::Create(reinterpret_cast<DebugInfoHeader*>(dbg_info),
+ dbg_info_size, abbrev.get()));
+ if (iter.get() == nullptr) {
+ return false;
+ }
+ return FixupDebugInfo(text_start, iter.get())
+ && FixupDebugFrame(text_start, dbg_frame, dbg_frame_size);
+}
void ElfFile::GdbJITSupport() {
// We only get here if we only are mapping the program header.
@@ -1000,18 +1313,25 @@ void ElfFile::GdbJITSupport() {
// Well, we need the whole file to do this.
std::string error_msg;
- std::unique_ptr<ElfFile> ptr(Open(const_cast<File*>(file_), false, false, &error_msg));
- ElfFile& all = *ptr;
-
- // Do we have interesting sections?
- // Is this an OAT file with interesting sections?
- if (all.GetSectionHeaderNum() != kExpectedSectionsInOATFile) {
+ // Make it MAP_PRIVATE so we can just give it to gdb if all the necessary
+ // sections are there.
+ std::unique_ptr<ElfFile> all_ptr(Open(const_cast<File*>(file_), PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, &error_msg));
+ if (all_ptr.get() == nullptr) {
return;
}
- if (!check_section_name(all, 8, ".debug_info") ||
- !check_section_name(all, 9, ".debug_abbrev") ||
- !check_section_name(all, 10, ".debug_frame") ||
- !check_section_name(all, 11, ".debug_str")) {
+ ElfFile& all = *all_ptr;
+
+ // Do we have interesting sections?
+ const Elf32_Shdr* debug_info = all.FindSectionByName(".debug_info");
+ const Elf32_Shdr* debug_abbrev = all.FindSectionByName(".debug_abbrev");
+ const Elf32_Shdr* debug_frame = all.FindSectionByName(".debug_frame");
+ const Elf32_Shdr* debug_str = all.FindSectionByName(".debug_str");
+ const Elf32_Shdr* strtab_sec = all.FindSectionByName(".strtab");
+ const Elf32_Shdr* symtab_sec = all.FindSectionByName(".symtab");
+ Elf32_Shdr* text_sec = all.FindSectionByName(".text");
+ if (debug_info == nullptr || debug_abbrev == nullptr || debug_frame == nullptr ||
+ debug_str == nullptr || text_sec == nullptr || strtab_sec == nullptr || symtab_sec == nullptr) {
return;
}
#ifdef __LP64__
@@ -1019,227 +1339,29 @@ void ElfFile::GdbJITSupport() {
return; // No ELF debug support in 64bit.
}
#endif
- // This is not needed if we have no .text segment.
- uint32_t text_start_addr = 0;
- for (uint32_t i = 0; i < segments_.size(); i++) {
- if (segments_[i]->GetProtect() & PROT_EXEC) {
- // We found the .text section.
- text_start_addr = PointerToLowMemUInt32(segments_[i]->Begin());
- break;
- }
- }
- if (text_start_addr == 0U) {
- return;
- }
-
- // Okay, we are good enough. Fake up an ELF image and tell GDB about it.
- // We need some extra space for the debug and string sections, the ELF header, and the
- // section header.
- uint32_t needed_size = KB;
-
- for (Elf32_Word i = 1; i < all.GetSectionHeaderNum(); i++) {
- Elf32_Shdr& section_header = all.GetSectionHeader(i);
- if (section_header.sh_addr == 0 && section_header.sh_type != SHT_DYNSYM) {
- // Debug section: we need it.
- needed_size += section_header.sh_size;
- } else if (section_header.sh_type == SHT_STRTAB &&
- strcmp(".shstrtab",
- all.GetString(SHT_SYMTAB, section_header.sh_name)) == 0) {
- // We also need the shared string table.
- needed_size += section_header.sh_size;
-
- // We also need the extra strings .symtab\0.strtab\0
- needed_size += 16;
- }
- }
-
- // Start creating our image.
- jit_elf_image_ = new byte[needed_size];
-
- // Create the Elf Header by copying the old one
- Elf32_Ehdr& elf_hdr =
- *reinterpret_cast<Elf32_Ehdr*>(jit_elf_image_);
-
- elf_hdr = all.GetHeader();
+ // We need to add in a strtab and symtab to the image.
+ // all is MAP_PRIVATE so it can be written to freely.
+ // We also already have strtab and symtab so we are fine there.
+ Elf32_Ehdr& elf_hdr = all.GetHeader();
elf_hdr.e_entry = 0;
elf_hdr.e_phoff = 0;
elf_hdr.e_phnum = 0;
elf_hdr.e_phentsize = 0;
elf_hdr.e_type = ET_EXEC;
- uint32_t offset = sizeof(Elf32_Ehdr);
-
- // Copy the debug sections and string table.
- uint32_t debug_offsets[kExpectedSectionsInOATFile];
- memset(debug_offsets, '\0', sizeof debug_offsets);
- Elf32_Shdr *text_header = nullptr;
- int extra_shstrtab_entries = -1;
- int text_section_index = -1;
- int section_index = 1;
- for (Elf32_Word i = 1; i < kExpectedSectionsInOATFile; i++) {
- Elf32_Shdr& section_header = all.GetSectionHeader(i);
- // Round up to multiple of 4, ensuring zero fill.
- RoundAndClear(jit_elf_image_, offset, 4);
- if (section_header.sh_addr == 0 && section_header.sh_type != SHT_DYNSYM) {
- // Debug section: we need it. Unfortunately, it wasn't mapped in.
- debug_offsets[i] = offset;
- // Read it from the file.
- lseek(file_->Fd(), section_header.sh_offset, SEEK_SET);
- read(file_->Fd(), jit_elf_image_ + offset, section_header.sh_size);
- offset += section_header.sh_size;
- section_index++;
- offset += 16;
- } else if (section_header.sh_type == SHT_STRTAB &&
- strcmp(".shstrtab",
- all.GetString(SHT_SYMTAB, section_header.sh_name)) == 0) {
- // We also need the shared string table.
- debug_offsets[i] = offset;
- // Read it from the file.
- lseek(file_->Fd(), section_header.sh_offset, SEEK_SET);
- read(file_->Fd(), jit_elf_image_ + offset, section_header.sh_size);
- offset += section_header.sh_size;
- // We also need the extra strings .symtab\0.strtab\0
- extra_shstrtab_entries = section_header.sh_size;
- memcpy(jit_elf_image_+offset, ".symtab\0.strtab\0", 16);
- offset += 16;
- section_index++;
- } else if (section_header.sh_flags & SHF_EXECINSTR) {
- DCHECK(strcmp(".text", all.GetString(SHT_SYMTAB,
- section_header.sh_name)) == 0);
- text_header = &section_header;
- text_section_index = section_index++;
- }
- }
- DCHECK(text_header != nullptr);
- DCHECK_NE(extra_shstrtab_entries, -1);
-
- // We now need to update the addresses for debug_info and debug_frame to get to the
- // correct offset within the .text section.
- byte *p = jit_elf_image_+debug_offsets[8];
- byte *end = p + all.GetSectionHeader(8).sh_size;
-
- // For debug_info; patch compilation using low_pc @ offset 13, high_pc at offset 17.
- IncrementUint32(p + 13, text_start_addr);
- IncrementUint32(p + 17, text_start_addr);
-
- // Now fix the low_pc, high_pc for each method address.
- // First method starts at offset 0x15, each subsequent method is 1+3*4 bytes further.
- for (p += 0x15; p < end; p += 1 /* attr# */ + 3 * sizeof(uint32_t) /* addresses */) {
- IncrementUint32(p + 1 + sizeof(uint32_t), text_start_addr);
- IncrementUint32(p + 1 + 2 * sizeof(uint32_t), text_start_addr);
- }
-
- // Now we have to handle the debug_frame method start addresses
- p = jit_elf_image_+debug_offsets[10];
- end = p + all.GetSectionHeader(10).sh_size;
-
- // Skip past the CIE.
- p += *reinterpret_cast<uint32_t *>(p) + 4;
-
- // And walk the FDEs.
- for (; p < end; p += *reinterpret_cast<uint32_t *>(p) + sizeof(uint32_t)) {
- IncrementUint32(p + 2 * sizeof(uint32_t), text_start_addr);
- }
-
- // Create the data for the symbol table.
- const int kSymbtabAlignment = 16;
- RoundAndClear(jit_elf_image_, offset, kSymbtabAlignment);
- uint32_t symtab_offset = offset;
-
- // First entry is empty.
- memset(jit_elf_image_+offset, 0, sizeof(Elf32_Sym));
- offset += sizeof(Elf32_Sym);
-
- // Symbol 1 is the real .text section.
- Elf32_Sym& sym_ent = *reinterpret_cast<Elf32_Sym*>(jit_elf_image_+offset);
- sym_ent.st_name = 1; /* .text */
- sym_ent.st_value = text_start_addr;
- sym_ent.st_size = text_header->sh_size;
- SetBindingAndType(&sym_ent, STB_LOCAL, STT_SECTION);
- sym_ent.st_other = 0;
- sym_ent.st_shndx = text_section_index;
- offset += sizeof(Elf32_Sym);
-
- // Create the data for the string table.
- RoundAndClear(jit_elf_image_, offset, kSymbtabAlignment);
- const int kTextStringSize = 7;
- uint32_t strtab_offset = offset;
- memcpy(jit_elf_image_+offset, "\0.text", kTextStringSize);
- offset += kTextStringSize;
-
- // Create the section header table.
- // Round up to multiple of kSymbtabAlignment, ensuring zero fill.
- RoundAndClear(jit_elf_image_, offset, kSymbtabAlignment);
- elf_hdr.e_shoff = offset;
- Elf32_Shdr *sp =
- reinterpret_cast<Elf32_Shdr *>(jit_elf_image_ + offset);
-
- // Copy the first empty index.
- *sp = all.GetSectionHeader(0);
- BUMP_SHENT(sp);
-
- elf_hdr.e_shnum = 1;
- for (Elf32_Word i = 1; i < kExpectedSectionsInOATFile; i++) {
- Elf32_Shdr& section_header = all.GetSectionHeader(i);
- if (section_header.sh_addr == 0 && section_header.sh_type != SHT_DYNSYM) {
- // Debug section: we need it.
- *sp = section_header;
- sp->sh_offset = debug_offsets[i];
- sp->sh_addr = 0;
- elf_hdr.e_shnum++;
- BUMP_SHENT(sp);
- } else if (section_header.sh_type == SHT_STRTAB &&
- strcmp(".shstrtab",
- all.GetString(SHT_SYMTAB, section_header.sh_name)) == 0) {
- // We also need the shared string table.
- *sp = section_header;
- sp->sh_offset = debug_offsets[i];
- sp->sh_size += 16; /* sizeof ".symtab\0.strtab\0" */
- sp->sh_addr = 0;
- elf_hdr.e_shstrndx = elf_hdr.e_shnum;
- elf_hdr.e_shnum++;
- BUMP_SHENT(sp);
- }
+ text_sec->sh_type = SHT_NOBITS;
+ text_sec->sh_offset = 0;
+
+ if (!FixupDebugSections(
+ all.Begin() + debug_abbrev->sh_offset, debug_abbrev->sh_size, text_sec->sh_addr,
+ all.Begin() + debug_info->sh_offset, debug_info->sh_size,
+ all.Begin() + debug_frame->sh_offset, debug_frame->sh_size)) {
+ LOG(ERROR) << "Failed to load GDB data";
+ return;
}
- // Add a .text section for the matching code section.
- *sp = *text_header;
- sp->sh_type = SHT_NOBITS;
- sp->sh_offset = 0;
- sp->sh_addr = text_start_addr;
- elf_hdr.e_shnum++;
- BUMP_SHENT(sp);
-
- // .symtab section: Need an empty index and the .text entry
- sp->sh_name = extra_shstrtab_entries;
- sp->sh_type = SHT_SYMTAB;
- sp->sh_flags = 0;
- sp->sh_addr = 0;
- sp->sh_offset = symtab_offset;
- sp->sh_size = 2 * sizeof(Elf32_Sym);
- sp->sh_link = elf_hdr.e_shnum + 1; // Link to .strtab section.
- sp->sh_info = 0;
- sp->sh_addralign = 16;
- sp->sh_entsize = sizeof(Elf32_Sym);
- elf_hdr.e_shnum++;
- BUMP_SHENT(sp);
-
- // .strtab section: Enough for .text\0.
- sp->sh_name = extra_shstrtab_entries + 8;
- sp->sh_type = SHT_STRTAB;
- sp->sh_flags = 0;
- sp->sh_addr = 0;
- sp->sh_offset = strtab_offset;
- sp->sh_size = kTextStringSize;
- sp->sh_link = 0;
- sp->sh_info = 0;
- sp->sh_addralign = 16;
- sp->sh_entsize = 0;
- elf_hdr.e_shnum++;
- BUMP_SHENT(sp);
-
- // We now have enough information to tell GDB about our file.
- jit_gdb_entry_ = CreateCodeEntry(jit_elf_image_, offset);
+ jit_gdb_entry_ = CreateCodeEntry(all.Begin(), all.Size());
+ gdb_file_mapping_.reset(all_ptr.release());
}
} // namespace art
diff --git a/runtime/elf_file.h b/runtime/elf_file.h
index 6650acd..496690b 100644
--- a/runtime/elf_file.h
+++ b/runtime/elf_file.h
@@ -41,6 +41,9 @@ extern "C" {
class ElfFile {
public:
static ElfFile* Open(File* file, bool writable, bool program_header_only, std::string* error_msg);
+ // Open with specific mmap flags, Always maps in the whole file, not just the
+ // program header sections.
+ static ElfFile* Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg);
~ElfFile();
// Load segments into memory based on PT_LOAD program headers
@@ -70,17 +73,19 @@ class ElfFile {
Elf32_Word GetSectionHeaderNum() const;
Elf32_Shdr& GetSectionHeader(Elf32_Word) const;
Elf32_Shdr* FindSectionByType(Elf32_Word type) const;
+ Elf32_Shdr* FindSectionByName(const std::string& name) const;
Elf32_Shdr& GetSectionNameStringSection() const;
// Find .dynsym using .hash for more efficient lookup than FindSymbolAddress.
const byte* FindDynamicSymbolAddress(const std::string& symbol_name) const;
+ const Elf32_Sym* FindDynamicSymbol(const std::string& symbol_name) const;
static bool IsSymbolSectionType(Elf32_Word section_type);
Elf32_Word GetSymbolNum(Elf32_Shdr&) const;
Elf32_Sym& GetSymbol(Elf32_Word section_type, Elf32_Word i) const;
- // Find symbol in specified table, returning NULL if it is not found.
+ // Find symbol in specified table, returning nullptr if it is not found.
//
// If build_map is true, builds a map to speed repeated access. The
// map does not included untyped symbol values (aka STT_NOTYPE)
@@ -98,11 +103,11 @@ class ElfFile {
const std::string& symbol_name,
bool build_map);
- // Lookup a string given string section and offset. Returns NULL for
+ // Lookup a string given string section and offset. Returns nullptr for
// special 0 offset.
const char* GetString(Elf32_Shdr&, Elf32_Word) const;
- // Lookup a string by section type. Returns NULL for special 0 offset.
+ // Lookup a string by section type. Returns nullptr for special 0 offset.
const char* GetString(Elf32_Word section_type, Elf32_Word) const;
Elf32_Word GetDynamicNum() const;
@@ -125,7 +130,7 @@ class ElfFile {
private:
ElfFile(File* file, bool writable, bool program_header_only);
- bool Setup(std::string* error_msg);
+ bool Setup(int prot, int flags, std::string* error_msg);
bool SetMap(MemMap* map, std::string* error_msg);
@@ -181,9 +186,8 @@ class ElfFile {
// Support for GDB JIT
byte* jit_elf_image_;
JITCodeEntry* jit_gdb_entry_;
+ std::unique_ptr<ElfFile> gdb_file_mapping_;
void GdbJITSupport();
- // Is this an OAT file with debug information in it?
- static constexpr uint32_t kExpectedSectionsInOATFile = 12;
};
} // namespace art