| /* DWARF CU data structure |
| |
| Copyright (C) 2021-2024 Free Software Foundation, Inc. |
| |
| This file is part of GDB. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| |
| #include "dwarf2/cu.h" |
| #include "dwarf2/read.h" |
| #include "objfiles.h" |
| #include "filenames.h" |
| #include "producer.h" |
| #include "gdbsupport/pathstuff.h" |
| |
| /* Initialize dwarf2_cu to read PER_CU, in the context of PER_OBJFILE. */ |
| |
| dwarf2_cu::dwarf2_cu (dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile) |
| : per_cu (per_cu), |
| per_objfile (per_objfile), |
| m_mark (false), |
| has_loclist (false), |
| m_checked_producer (false), |
| m_producer_is_gxx_lt_4_6 (false), |
| m_producer_is_gcc_lt_4_5 (false), |
| m_producer_is_gcc_lt_4_3 (false), |
| m_producer_is_gcc_ge_4 (false), |
| m_producer_is_gcc_11 (false), |
| m_producer_is_gcc (false), |
| m_producer_is_icc (false), |
| m_producer_is_icc_lt_14 (false), |
| m_producer_is_codewarrior (false), |
| m_producer_is_clang (false), |
| m_producer_is_gas_lt_2_38 (false), |
| m_producer_is_gas_2_39 (false), |
| m_producer_is_gas_ge_2_40 (false), |
| m_producer_is_realview (false), |
| m_producer_is_xlc (false), |
| m_producer_is_xlc_opencl (false), |
| m_producer_is_gf77 (false), |
| m_producer_is_ggo (false), |
| processing_has_namespace_info (false) |
| { |
| } |
| |
| /* See cu.h. */ |
| |
| struct type * |
| dwarf2_cu::addr_sized_int_type (bool unsigned_p) const |
| { |
| int addr_size = this->per_cu->addr_size (); |
| return objfile_int_type (this->per_objfile->objfile, addr_size, unsigned_p); |
| } |
| |
| /* Start a symtab for DWARF. NAME, COMP_DIR, LOW_PC are passed to the |
| buildsym_compunit constructor. */ |
| |
| struct compunit_symtab * |
| dwarf2_cu::start_compunit_symtab (const char *name, const char *comp_dir, |
| CORE_ADDR low_pc) |
| { |
| gdb_assert (m_builder == nullptr); |
| |
| std::string name_for_id_holder; |
| const char *name_for_id = name; |
| |
| /* Prepend the compilation directory to the filename if needed (if not |
| absolute already) to get the "name for id" for our main symtab. The name |
| for the main file coming from the line table header will be generated using |
| the same logic, so will hopefully match what we pass here. */ |
| if (!IS_ABSOLUTE_PATH (name) && comp_dir != nullptr) |
| { |
| name_for_id_holder = path_join (comp_dir, name); |
| name_for_id = name_for_id_holder.c_str (); |
| } |
| |
| m_builder = std::make_unique<buildsym_compunit> (this->per_objfile->objfile, |
| name, |
| comp_dir, |
| name_for_id, |
| lang (), |
| low_pc); |
| |
| list_in_scope = get_builder ()->get_file_symbols (); |
| |
| /* DWARF versions are restricted to [2, 5], thanks to the check in |
| read_comp_unit_head. */ |
| gdb_assert (this->header.version >= 2 && this->header.version <= 5); |
| static const char *debugformat_strings[] = { |
| "DWARF 2", |
| "DWARF 3", |
| "DWARF 4", |
| "DWARF 5", |
| }; |
| const char *debugformat = debugformat_strings[this->header.version - 2]; |
| |
| get_builder ()->record_debugformat (debugformat); |
| get_builder ()->record_producer (m_producer); |
| |
| processing_has_namespace_info = false; |
| |
| return get_builder ()->get_compunit_symtab (); |
| } |
| |
| /* See read.h. */ |
| |
| struct type * |
| dwarf2_cu::addr_type () const |
| { |
| struct objfile *objfile = this->per_objfile->objfile; |
| struct type *void_type = builtin_type (objfile)->builtin_void; |
| struct type *addr_type = lookup_pointer_type (void_type); |
| int addr_size = this->per_cu->addr_size (); |
| |
| if (addr_type->length () == addr_size) |
| return addr_type; |
| |
| addr_type = addr_sized_int_type (addr_type->is_unsigned ()); |
| return addr_type; |
| } |
| |
| /* See dwarf2/cu.h. */ |
| |
| void |
| dwarf2_cu::mark () |
| { |
| if (m_mark) |
| return; |
| |
| m_mark = true; |
| |
| for (dwarf2_per_cu *per_cu : m_dependencies) |
| { |
| /* cu->m_dependencies references may not yet have been ever |
| read if QUIT aborts reading of the chain. As such |
| dependencies remain valid it is not much useful to track |
| and undo them during QUIT cleanups. */ |
| dwarf2_cu *cu = per_objfile->get_cu (per_cu); |
| |
| if (cu == nullptr) |
| continue; |
| |
| cu->mark (); |
| } |
| } |
| |
| /* See dwarf2/cu.h. */ |
| |
| buildsym_compunit * |
| dwarf2_cu::get_builder () |
| { |
| /* If this CU has a builder associated with it, use that. */ |
| if (m_builder != nullptr) |
| return m_builder.get (); |
| |
| if (per_objfile->sym_cu != nullptr) |
| return per_objfile->sym_cu->m_builder.get (); |
| |
| gdb_assert_not_reached (""); |
| } |
| |
| /* See dwarf2/cu.h. */ |
| |
| void |
| dwarf2_cu::set_producer (const char *producer) |
| { |
| gdb_assert (m_producer == nullptr || strcmp (producer, m_producer) == 0); |
| m_producer = producer; |
| |
| int major, minor; |
| |
| if (m_producer == nullptr) |
| { |
| /* For unknown compilers expect their behavior is DWARF version |
| compliant. |
| |
| GCC started to support .debug_types sections by -gdwarf-4 since |
| gcc-4.5.x. As the .debug_types sections are missing DW_AT_producer |
| for their space efficiency GDB cannot workaround gcc-4.5.x -gdwarf-4 |
| combination. gcc-4.5.x -gdwarf-4 binaries have DW_AT_accessibility |
| interpreted incorrectly by GDB now - GCC PR debug/48229. */ |
| } |
| else if (::producer_is_gcc (m_producer, &major, &minor)) |
| { |
| m_producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6); |
| m_producer_is_gcc_lt_4_5 = major < 4 || (major == 4 && minor < 5); |
| m_producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3); |
| m_producer_is_gcc_ge_4 = major >= 4; |
| m_producer_is_gcc_11 = major == 11; |
| m_producer_is_gcc = true; |
| } |
| else if (::producer_is_icc (m_producer, &major, &minor)) |
| { |
| m_producer_is_icc = true; |
| m_producer_is_icc_lt_14 = major < 14; |
| } |
| else if (startswith (m_producer, "CodeWarrior S12/L-ISA")) |
| m_producer_is_codewarrior = true; |
| else if (::producer_is_clang (m_producer, &major, &minor)) |
| m_producer_is_clang = true; |
| else if (::producer_is_gas (m_producer, &major, &minor)) |
| { |
| m_producer_is_gas_lt_2_38 = major < 2 || (major == 2 && minor < 38); |
| m_producer_is_gas_2_39 = major == 2 && minor == 39; |
| m_producer_is_gas_ge_2_40 = major > 2 || (major == 2 && minor >= 40); |
| } |
| else if (::producer_is_realview (m_producer)) |
| m_producer_is_realview = true; |
| else if (startswith (m_producer, "IBM(R) XL C/C++ Advanced Edition")) |
| m_producer_is_xlc = true; |
| else if (strstr (m_producer, "IBM XL C for OpenCL") != nullptr) |
| m_producer_is_xlc_opencl = true; |
| else |
| { |
| /* For other non-GCC compilers, expect their behavior is DWARF version |
| compliant. */ |
| } |
| |
| if (m_producer != nullptr) |
| { |
| if (strstr (m_producer, "GNU F77") != nullptr) |
| m_producer_is_gf77 = true; |
| else if (strstr (m_producer, "GNU Go ") != nullptr) |
| m_producer_is_ggo = true; |
| } |
| |
| m_checked_producer = true; |
| } |