X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/83339f7ee7c47e16583c280915b853a98c59b923..5c193dfc57256298e9b04e4a2fe887135ca49b86:/src/mc/mc_dwarf.cpp diff --git a/src/mc/mc_dwarf.cpp b/src/mc/mc_dwarf.cpp index dc7736a29a..8be805343d 100644 --- a/src/mc/mc_dwarf.cpp +++ b/src/mc/mc_dwarf.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2015. The SimGrid Team. +/* Copyright (c) 2008-2017. The SimGrid Team. * All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it @@ -7,28 +7,30 @@ #include #include -#include #include #include +#include + #include #include #define DW_LANG_Objc DW_LANG_ObjC /* fix spelling error in older dwarf.h */ #include #include -#include +#include + #include "src/simgrid/util.hpp" -#include -#include +#include "xbt/log.h" +#include "xbt/sysdep.h" +#include #include "src/mc/mc_private.h" #include "src/mc/mc_dwarf.hpp" -#include "src/mc/mc_object_info.h" -#include "src/mc/Process.hpp" #include "src/mc/ObjectInformation.hpp" #include "src/mc/Variable.hpp" +#include "src/mc/remote/RemoteClient.hpp" XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dwarf, mc, "DWARF processing"); @@ -36,7 +38,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dwarf, mc, "DWARF processing"); * * The default for a given language is defined in the DWARF spec. * - * \param language consant as defined by the DWARf spec + * \param language constant as defined by the DWARf spec */ static uint64_t MC_dwarf_default_lower_bound(int lang); @@ -51,8 +53,7 @@ static uint64_t MC_dwarf_default_lower_bound(int lang); * \param die DIE for the DW_TAG_enumeration_type or DW_TAG_subrange_type * \param unit DIE of the DW_TAG_compile_unit */ -static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die * die, - Dwarf_Die * unit); +static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die* die, Dwarf_Die* unit); /** \brief Computes the number of elements of a given DW_TAG_array_type. * @@ -65,7 +66,7 @@ static uint64_t MC_dwarf_array_element_count(Dwarf_Die * die, Dwarf_Die * unit); * \param info the resulting object fot the library/binary file (output) * \param die the current DIE * \param unit the DIE of the compile unit of the current DIE - * \param frame containg frame if any + * \param frame containing frame if any */ static void MC_dwarf_handle_die(simgrid::mc::ObjectInformation* info, Dwarf_Die * die, Dwarf_Die * unit, simgrid::mc::Frame* frame, @@ -77,12 +78,12 @@ static void MC_dwarf_handle_type_die(simgrid::mc::ObjectInformation* info, Dwarf Dwarf_Die * unit, simgrid::mc::Frame* frame, const char *ns); -/** \brief Calls MC_dwarf_handle_die on all childrend of the given die +/** \brief Calls MC_dwarf_handle_die on all children of the given die * * \param info the resulting object fot the library/binary file (output) * \param die the current DIE * \param unit the DIE of the compile unit of the current DIE - * \param frame containg frame if any + * \param frame containing frame if any */ static void MC_dwarf_handle_children(simgrid::mc::ObjectInformation* info, Dwarf_Die * die, Dwarf_Die * unit, simgrid::mc::Frame* frame, @@ -93,7 +94,7 @@ static void MC_dwarf_handle_children(simgrid::mc::ObjectInformation* info, Dwarf * \param info the resulting object fot the library/binary file (output) * \param die the current DIE * \param unit the DIE of the compile unit of the current DIE - * \param frame containg frame if any + * \param frame containing frame if any */ static void MC_dwarf_handle_variable_die(simgrid::mc::ObjectInformation* info, Dwarf_Die * die, Dwarf_Die * unit, simgrid::mc::Frame* frame, @@ -259,7 +260,7 @@ static const char *MC_dwarf_attr_integrate_string(Dwarf_Die * die, int attribute) { Dwarf_Attribute attr; - if (!dwarf_attr_integrate(die, attribute, &attr)) + if (not dwarf_attr_integrate(die, attribute, &attr)) return nullptr; else return dwarf_formstring(&attr); @@ -278,7 +279,7 @@ static const char *MC_dwarf_attr_integrate_string(Dwarf_Die * die, static const char *MC_dwarf_at_linkage_name(Dwarf_Die * die) { const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_linkage_name); - if (!name) + if (not name) name = MC_dwarf_attr_integrate_string(die, DW_AT_MIPS_linkage_name); return name; } @@ -356,13 +357,13 @@ static bool MC_dwarf_attr_flag(Dwarf_Die * die, int attribute, bool integrate) return result; } -/** \brief Find the default lower bound for a given language +/** @brief Find the default lower bound for a given language * * The default lower bound of an array (when DW_TAG_lower_bound * is missing) depends on the language of the compilation unit. * - * \param lang Language of the compilation unit (values defined in the DWARF spec) - * \return Default lower bound of an array in this compilation unit + * @param lang Language of the compilation unit (values defined in the DWARF spec) + * @return Default lower bound of an array in this compilation unit * */ static uint64_t MC_dwarf_default_lower_bound(int lang) { @@ -415,7 +416,7 @@ static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die * die, return MC_dwarf_attr_integrate_uint(die, DW_AT_count, 0); // Otherwise compute DW_TAG_upper_bound-DW_TAG_lower_bound + 1: - if (!dwarf_hasattr_integrate(die, DW_AT_upper_bound)) + if (not dwarf_hasattr_integrate(die, DW_AT_upper_bound)) // This is not really 0, but the code expects this (we do not know): return 0; @@ -491,7 +492,7 @@ static void MC_dwarf_fill_member_location( if (dwarf_hasattr(child, DW_AT_data_bit_offset)) xbt_die("Can't groke DW_AT_data_bit_offset."); - if (!dwarf_hasattr_integrate(child, DW_AT_data_member_location)) { + if (not dwarf_hasattr_integrate(child, DW_AT_data_member_location)) { if (type->type == DW_TAG_union_type) return; xbt_die @@ -523,7 +524,7 @@ static void MC_dwarf_fill_member_location( // Offset from the base address of the object: { Dwarf_Word offset; - if (!dwarf_formudata(&attr, &offset)) + if (not dwarf_formudata(&attr, &offset)) member->offset(offset); else xbt_die("Cannot get %s location <%" PRIx64 ">%s", @@ -538,8 +539,7 @@ static void MC_dwarf_fill_member_location( // It's supposed to be possible in DWARF2 but I couldn't find its semantic // in the spec. default: - xbt_die("Can't handle form class (%i) / form 0x%x as DW_AT_member_location", - (int) form_class, form); + xbt_die("Can't handle form class (%d) / form 0x%x as DW_AT_member_location", (int)form_class, (unsigned)form); } } @@ -572,11 +572,35 @@ static void MC_dwarf_add_members(simgrid::mc::ObjectInformation* info, Dwarf_Die // TODO, we should use another type (because is is not a type but a member) simgrid::mc::Member member; - member.inheritance = tag == DW_TAG_inheritance; + if (tag == DW_TAG_inheritance) + member.flags |= simgrid::mc::Member::INHERITANCE_FLAG; const char *name = MC_dwarf_attr_integrate_string(&child, DW_AT_name); if (name) member.name = name; + // Those base names are used by GCC and clang for virtual table pointers + // respectively ("__vptr$ClassName", "__vptr.ClassName"): + if (boost::algorithm::starts_with(member.name, "__vptr$") || + boost::algorithm::starts_with(member.name, "__vptr.")) + member.flags |= simgrid::mc::Member::VIRTUAL_POINTER_FLAG; + // A cleaner solution would be to check against the type: + // --- + // tag: DW_TAG_member + // name: "_vptr$Foo" + // type: + // # Type for a pointer to a vtable + // tag: DW_TAG_pointer_type + // type: + // # Type for a vtable: + // tag: DW_TAG_pointer_type + // name: "__vtbl_ptr_type" + // type: + // tag: DW_TAG_subroutine_type + // type: + // tag: DW_TAG_base_type + // name: "int" + // --- + member.byte_size = MC_dwarf_attr_integrate_uint(&child, DW_AT_byte_size, 0); member.type_id = MC_dwarf_at_type(&child); @@ -586,7 +610,7 @@ static void MC_dwarf_add_members(simgrid::mc::ObjectInformation* info, Dwarf_Die MC_dwarf_fill_member_location(type, &member, &child); - if (!member.type_id) + if (not member.type_id) xbt_die("Missing type for member %s of <%" PRIx64 ">%s", member.name.c_str(), (uint64_t) type->id, type->name.c_str()); @@ -680,7 +704,7 @@ static simgrid::mc::Type MC_dwarf_die_to_type( break; } - return std::move(type); + return type; } static void MC_dwarf_handle_type_die(simgrid::mc::ObjectInformation* info, Dwarf_Die * die, @@ -689,7 +713,7 @@ static void MC_dwarf_handle_type_die(simgrid::mc::ObjectInformation* info, Dwarf { simgrid::mc::Type type = MC_dwarf_die_to_type(info, die, unit, frame, ns); auto& t = (info->types[type.id] = std::move(type)); - if (!t.name.empty() && type.byte_size != 0) + if (not t.name.empty() && type.byte_size != 0) info->full_types_by_name[t.name] = &t; } @@ -715,7 +739,7 @@ static std::unique_ptr MC_die_to_variable( std::unique_ptr variable = std::unique_ptr(new simgrid::mc::Variable()); - variable->dwarf_offset = dwarf_dieoffset(die); + variable->id = dwarf_dieoffset(die); variable->global = frame == nullptr; // Can be override base on DW_AT_location variable->object_info = info; @@ -741,12 +765,12 @@ static std::unique_ptr MC_die_to_variable( xbt_die( "Could not read location expression in DW_AT_location " "of variable <%" PRIx64 ">%s", - (uint64_t) variable->dwarf_offset, + (uint64_t) variable->id, variable->name.c_str()); } if (len == 1 && expr[0].atom == DW_OP_addr) { - variable->global = 1; + variable->global = true; uintptr_t offset = (uintptr_t) expr[0].number; uintptr_t base = (uintptr_t) info->base_address(); variable->address = (void *) (base + offset); @@ -765,11 +789,8 @@ static std::unique_ptr MC_die_to_variable( break; default: - xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location " - "in <%" PRIx64 ">%s", - form, form, (int) form_class, (int) form_class, - (uint64_t) variable->dwarf_offset, - variable->name.c_str()); + xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location in <%" PRIx64 ">%s", (unsigned)form, form, + (unsigned)form_class, (int)form_class, (uint64_t)variable->id, variable->name.c_str()); } // Handle start_scope: @@ -789,9 +810,8 @@ static std::unique_ptr MC_die_to_variable( case simgrid::dwarf::FormClass::RangeListPtr: // TODO default: - xbt_die - ("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s", - form, (int) form_class, name == nullptr ? "?" : name); + xbt_die("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s", (unsigned)form, + (unsigned)form_class, name == nullptr ? "?" : name); } } @@ -805,7 +825,7 @@ static std::unique_ptr MC_die_to_variable( variable->name = "@anonymous#" + std::to_string(mc_anonymous_variable_index++); - return std::move(variable); + return variable; } static void MC_dwarf_handle_variable_die(simgrid::mc::ObjectInformation* info, Dwarf_Die * die, @@ -814,7 +834,7 @@ static void MC_dwarf_handle_variable_die(simgrid::mc::ObjectInformation* info, D { std::unique_ptr variable = MC_die_to_variable(info, die, unit, frame, ns); - if (!variable) + if (not variable) return; // Those arrays are sorted later: else if (variable->global) @@ -848,7 +868,7 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar if (klass == simgrid::dwarf::TagClass::Subprogram) { const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name); - if (ns) + if (name && ns) frame.name = std::string(ns) + "::" + name; else if (name) frame.name = name; @@ -868,7 +888,7 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar if (low_pc) { // DW_AT_high_pc: Dwarf_Attribute attr; - if (!dwarf_attr_integrate(die, DW_AT_high_pc, &attr)) + if (not dwarf_attr_integrate(die, DW_AT_high_pc, &attr)) xbt_die("Missing DW_AT_high_pc matching with DW_AT_low_pc"); Dwarf_Sword offset; @@ -888,7 +908,7 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar case simgrid::dwarf::FormClass::Address: if (dwarf_formaddr(&attr, &high_pc) != 0) xbt_die("Could not read address"); - frame.range.begin() = base + high_pc; + frame.range.end() = base + high_pc; break; default: @@ -909,8 +929,7 @@ static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwar // We sort them in order to have an (somewhat) efficient by name // lookup: - std::sort(frame.variables.begin(), frame.variables.end(), - MC_compare_variable); + boost::range::sort(frame.variables, MC_compare_variable); // Register it: if (klass == simgrid::dwarf::TagClass::Subprogram) @@ -999,11 +1018,11 @@ void read_dwarf_info(simgrid::mc::ObjectInformation* info, Dwarf* dwarf) Dwarf_Off next_offset = 0; size_t length; - while (dwarf_nextcu(dwarf, offset, &next_offset, &length, nullptr, NULL, NULL) == + while (dwarf_nextcu(dwarf, offset, &next_offset, &length, nullptr, nullptr, nullptr) == 0) { Dwarf_Die unit_die; if (dwarf_offdie(dwarf, offset + length, &unit_die) != nullptr) - MC_dwarf_handle_children(info, &unit_die, &unit_die, nullptr, NULL); + MC_dwarf_handle_children(info, &unit_die, &unit_die, nullptr, nullptr); offset = next_offset; } } @@ -1019,6 +1038,10 @@ void read_dwarf_info(simgrid::mc::ObjectInformation* info, Dwarf* dwarf) static std::vector get_build_id(Elf* elf) { +#ifdef __linux + // Summary: the GNU build ID is stored in a ("GNU, NT_GNU_BUILD_ID) note + // found in a PT_NOTE entry in the program header table. + size_t phnum; if (elf_getphdrnum (elf, &phnum) != 0) xbt_die("Could not read program headers"); @@ -1034,26 +1057,26 @@ std::vector get_build_id(Elf* elf) // Iterate over the notes and find the NT_GNU_BUILD_ID one: size_t pos = 0; - while (1) { + while (pos < data->d_size) { GElf_Nhdr nhdr; + // Location of the name within Elf_Data: size_t name_pos; size_t desc_pos; pos = gelf_getnote(data, pos, &nhdr, &name_pos, &desc_pos); - // A note is identified by a name "GNU" and a integer type within - // the namespace defined by this name (here NT_GNU_BUILD_ID): + // A build ID note is identified by the pair ("GNU", NT_GNU_BUILD_ID) + // (a namespace and a type within this namespace): if (nhdr.n_type == NT_GNU_BUILD_ID && nhdr.n_namesz == sizeof("GNU") && memcmp((char*) data->d_buf + name_pos, "GNU", sizeof("GNU")) == 0) { - - // Found the NT_GNU_BUILD_ID note: + XBT_DEBUG("Found GNU/NT_GNU_BUILD_ID note"); char* start = (char*) data->d_buf + desc_pos; char* end = (char*) start + nhdr.n_descsz; return std::vector(start, end); - } } } +#endif return std::vector(); } @@ -1082,7 +1105,7 @@ std::string to_hex(const char* data, std::size_t count) for (int j = 0; j < 2; ++j) res[2 * i + j] = hex_byte[j]; } - return std::move(res); + return res; } /** Binary data to hexadecimal */ @@ -1093,6 +1116,7 @@ std::string to_hex(std::vector const& data) } /** Base directories for external debug files */ +static const char* debug_paths[] = { "/usr/lib/debug/", "/usr/local/lib/debug/", @@ -1103,18 +1127,25 @@ const char* debug_paths[] = { * This is one of the mechanisms used for * [separate debug files](https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html). */ +// Example: +// /usr/lib/debug/.build-id/0b/dc77f1c29aea2b14ff5acd9a19ab3175ffdeae.debug static std::string find_by_build_id(std::vector id) { std::string filename; - for (const char* debug_path : debug_paths) { - filename = debug_path; - filename += ".build-id/" + to_hex(id.data(), 1) + '/' + std::string hex = to_hex(id); + for (const char* const& debug_path : debug_paths) { + // Example: + filename = std::string(debug_path) + ".build-id/" + + to_hex(id.data(), 1) + '/' + to_hex(id.data() + 1, id.size() - 1) + ".debug"; XBT_DEBUG("Checking debug file: %s", filename.c_str()); - if (access(filename.c_str(), F_OK) == 0) - return std::move(filename); + if (access(filename.c_str(), F_OK) == 0) { + XBT_DEBUG("Found debug file: %s\n", hex.c_str()); + return filename; + } } + XBT_DEBUG("Not debuf info found for build ID %s\n", hex.data()); return std::string(); } @@ -1124,7 +1155,7 @@ std::string find_by_build_id(std::vector id) * lists of types, variables, functions. */ static -void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info) +void MC_load_dwarf(simgrid::mc::ObjectInformation* info) { if (elf_version(EV_CURRENT) == EV_NONE) xbt_die("libelf initialization error"); @@ -1135,12 +1166,12 @@ void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info) xbt_die("Could not open file %s", info->file_name.c_str()); Elf* elf = elf_begin(fd, ELF_C_READ, nullptr); if (elf == nullptr) - xbt_die("Not an ELF file 1"); + xbt_die("Not an ELF file"); Elf_Kind kind = elf_kind(elf); if (kind != ELF_K_ELF) - xbt_die("Not an ELF file 2"); + xbt_die("Not an ELF file"); - // Remember if this is a `ET_EXEC` (fixed location) or `ET_DYN` (relocatable): + // Remember if this is a `ET_EXEC` (fixed location) or `ET_DYN`: Elf64_Half type = get_type(elf); if (type == ET_EXEC) info->flags |= simgrid::mc::ObjectInformation::Executable; @@ -1156,10 +1187,17 @@ void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info) } dwarf_end(dwarf); - // If there was no DWARF in the file, try to find it in a separate file - // with NT_GNU_BUILD_ID: + // If there was no DWARF in the file, try to find it in a separate file. + // Different methods might be used to store the DWARF informations: + // * GNU NT_GNU_BUILD_ID; + // * .gnu_debuglink. + // See https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html + // for reference of what we are doing. + + // Try with NT_GNU_BUILD_ID: we find the build ID in the ELF file and then + // use this ID to find the file in some known locations in the filesystem. std::vector build_id = get_build_id(elf); - if (!build_id.empty()) { + if (not build_id.empty()) { elf_end(elf); close(fd); @@ -1167,8 +1205,7 @@ void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info) std::string debug_file = find_by_build_id(build_id); if (debug_file.empty()) { std::string hex = to_hex(build_id); - xbt_die( - "Missing debug info for %s with build-id %s\n" + xbt_die("Missing debug info for %s with build-id %s\n" "You might want to install the suitable debugging package.\n", info->file_name.c_str(), hex.c_str()); } @@ -1189,9 +1226,10 @@ void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info) return; } - // TODO, try to find DWARF info using debug-link. - // Is this method really used anywhere? + // TODO, try to find DWARF info using .gnu_debuglink. + elf_end(elf); + close(fd); xbt_die("Debugging information not found for %s\n" "Try recompiling with -g\n", info->file_name.c_str()); @@ -1226,7 +1264,7 @@ static void MC_make_functions_index(simgrid::mc::ObjectInformation* info) info->functions_index.shrink_to_fit(); // Sort the array by low_pc: - std::sort(info->functions_index.begin(), info->functions_index.end(), + boost::range::sort(info->functions_index, [](simgrid::mc::FunctionIndexEntry const& a, simgrid::mc::FunctionIndexEntry const& b) { @@ -1237,10 +1275,9 @@ static void MC_make_functions_index(simgrid::mc::ObjectInformation* info) static void MC_post_process_variables(simgrid::mc::ObjectInformation* info) { // Someone needs this to be sorted but who? - std::sort(info->global_variables.begin(), info->global_variables.end(), - MC_compare_variable); + boost::range::sort(info->global_variables, MC_compare_variable); - for(simgrid::mc::Variable& variable : info->global_variables) + for (simgrid::mc::Variable& variable : info->global_variables) if (variable.type_id) variable.type = simgrid::util::find_map_ptr( info->types, variable.type_id); @@ -1266,15 +1303,14 @@ static void mc_post_process_scope(simgrid::mc::ObjectInformation* info, simgrid: // Recursive post-processing of nested-scopes: for (simgrid::mc::Frame& nested_scope : scope->scopes) - mc_post_process_scope(info, &nested_scope); - + mc_post_process_scope(info, &nested_scope); } static simgrid::mc::Type* MC_resolve_type( simgrid::mc::ObjectInformation* info, unsigned type_id) { - if (!type_id) + if (not type_id) return nullptr; simgrid::mc::Type* type = simgrid::util::find_map_ptr(info->types, type_id); if (type == nullptr) @@ -1300,33 +1336,36 @@ simgrid::mc::Type* MC_resolve_type( static void MC_post_process_types(simgrid::mc::ObjectInformation* info) { // Lookup "subtype" field: - for(auto& i : info->types) { + for (auto& i : info->types) { i.second.subtype = MC_resolve_type(info, i.second.type_id); for (simgrid::mc::Member& member : i.second.members) member.type = MC_resolve_type(info, member.type_id); } } +namespace simgrid { +namespace mc { + /** \brief Finds informations about a given shared object/executable */ -std::shared_ptr MC_find_object_info( +std::shared_ptr createObjectInformation( std::vector const& maps, const char *name) { std::shared_ptr result = std::make_shared(); result->file_name = name; simgrid::mc::find_object_address(maps, result.get()); - MC_dwarf_get_variables(result.get()); + MC_load_dwarf(result.get()); MC_post_process_variables(result.get()); MC_post_process_types(result.get()); for (auto& entry : result.get()->subprograms) mc_post_process_scope(result.get(), &entry.second); MC_make_functions_index(result.get()); - return std::move(result); + return result; } /*************************************************************************/ -void MC_post_process_object_info(simgrid::mc::Process* process, simgrid::mc::ObjectInformation* info) +void postProcessObjectInformation(simgrid::mc::RemoteClient* process, simgrid::mc::ObjectInformation* info) { for (auto& i : info->types) { @@ -1341,11 +1380,10 @@ void MC_post_process_object_info(simgrid::mc::Process* process, simgrid::mc::Obj break; // Resolve full_type: - if (!subtype->name.empty() && subtype->byte_size == 0) + if (not subtype->name.empty() && subtype->byte_size == 0) for (auto const& object_info : process->object_infos) { auto i = object_info->full_types_by_name.find(subtype->name); - if (i != object_info->full_types_by_name.end() - && !i->second->name.empty() && i->second->byte_size) { + if (i != object_info->full_types_by_name.end() && not i->second->name.empty() && i->second->byte_size) { type->full_type = i->second; break; } @@ -1355,6 +1393,9 @@ void MC_post_process_object_info(simgrid::mc::Process* process, simgrid::mc::Obj } } +} +} + namespace simgrid { namespace dwarf { @@ -1362,7 +1403,7 @@ namespace dwarf { * * DWARF and libunwind does not use the same convention for numbering the * registers on some architectures. The function makes the necessary - * convertion. + * conversion. */ int dwarf_register_to_libunwind(int dwarf_register) { @@ -1370,7 +1411,7 @@ int dwarf_register_to_libunwind(int dwarf_register) // It seems for this arch, DWARF and libunwind agree in the numbering: return dwarf_register; #elif defined(__i386__) - // Could't find the authoritative source of information for this. + // Couldn't find the authoritative source of information for this. // This is inspired from http://source.winehq.org/source/dlls/dbghelp/cpu_i386.c#L517. switch (dwarf_register) { case 0: