Replace readdir_r with readdir
[platform/upstream/ltrace.git] / dwarf_prototypes.c
index 8466c88..9c36904 100644 (file)
@@ -201,7 +201,7 @@ static bool get_integer_base_type(enum arg_type *type, int byte_size,
 static enum arg_type get_base_type(Dwarf_Die *die)
 {
        uint64_t encoding;
-       if (!get_die_numeric((uint64_t*)&encoding, die, DW_AT_encoding))
+       if (!get_die_numeric(&encoding, die, DW_AT_encoding))
                return ARGTYPE_VOID;
 
        if (encoding == DW_ATE_void)
@@ -328,7 +328,10 @@ static struct arg_type_info *get_enum(Dwarf_Die *parent,
                CLEANUP_AND_RETURN_ERROR(NULL);
        }
 
-       dict_insert(type_dieoffset_hash, &die_offset, &result);
+       if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) {
+               complain(parent, "Couldn't insert into cache dict");
+               CLEANUP_AND_RETURN_ERROR(NULL);
+       }
 
        uint64_t byte_size;
        if (!get_die_numeric(&byte_size, parent, DW_AT_byte_size)) {
@@ -465,7 +468,10 @@ static struct arg_type_info *get_array(Dwarf_Die *parent,
                CLEANUP_AND_RETURN_ERROR(NULL);
        }
 
-       dict_insert(type_dieoffset_hash, &die_offset, &result);
+       if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) {
+               complain(parent, "Couldn't insert into cache dict");
+               CLEANUP_AND_RETURN_ERROR(NULL);
+       }
        array_type = get_type(&newly_allocated_array_type,
                              &type_die, plib, type_dieoffset_hash);
        if (array_type == NULL) {
@@ -574,7 +580,10 @@ static struct arg_type_info *get_structure(Dwarf_Die *parent,
                CLEANUP_AND_RETURN_ERROR(NULL);
        }
        type_init_struct(result);
-       dict_insert(type_dieoffset_hash, &die_offset, &result);
+       if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) {
+               complain(parent, "Couldn't insert into cache dict");
+               CLEANUP_AND_RETURN_ERROR(NULL);
+       }
 
        Dwarf_Die die;
        if (dwarf_child(parent, &die) != 0) {
@@ -605,8 +614,11 @@ static struct arg_type_info *get_structure(Dwarf_Die *parent,
                        complain(&die, "Couldn't parse type from DWARF data");
                        CLEANUP_AND_RETURN_ERROR(NULL);
                }
-               type_struct_add(result, member_type,
-                               newly_allocated_member_type);
+               if (type_struct_add(result, member_type,
+                                   newly_allocated_member_type) != 0) {
+                       complain(&die, "Couldn't add type to struct");
+                       CLEANUP_AND_RETURN_ERROR(NULL);
+               }
 
                NEXT_SIBLING(&die);
        }
@@ -641,6 +653,16 @@ static struct arg_type_info *get_type(int *newly_allocated_result,
                return ret;                                             \
        } while (0)
 
+#define DICT_INSERT_AND_CHECK(type_dieoffset_hash, die_offset, result) \
+       do {                                                            \
+               if (dict_insert(type_dieoffset_hash,                    \
+                               die_offset, result) != 0) {             \
+                       complain(type_die,                              \
+                                "Couldn't insert into cache dict");    \
+                       CLEANUP_AND_RETURN_ERROR(NULL);                 \
+               }                                                       \
+       } while(0)
+
        struct arg_type_info *result = NULL;
        struct arg_type_info *pointee = NULL;
        int newly_allocated_pointee = 0;
@@ -680,7 +702,7 @@ static struct arg_type_info *get_type(int *newly_allocated_result,
        case DW_TAG_base_type:
                complain(type_die, "Storing base type");
                result = type_get_simple(get_base_type(type_die));
-               dict_insert(type_dieoffset_hash, &die_offset, &result);
+               DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
                return result;
 
        case DW_TAG_subroutine_type:
@@ -689,7 +711,7 @@ static struct arg_type_info *get_type(int *newly_allocated_result,
                // dereference these, it'll get a segfault
                complain(type_die, "Storing subroutine type");
                result = type_get_simple(ARGTYPE_VOID);
-               dict_insert(type_dieoffset_hash, &die_offset, &result);
+               DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
                return result;
 
        case DW_TAG_pointer_type:
@@ -698,7 +720,7 @@ static struct arg_type_info *get_type(int *newly_allocated_result,
                        // void*
                        complain(type_die, "Storing void-pointer type");
                        result = type_get_voidptr();
-                       dict_insert(type_dieoffset_hash, &die_offset, &result);
+                       DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
                        return result;
                }
 
@@ -710,7 +732,7 @@ static struct arg_type_info *get_type(int *newly_allocated_result,
                        complain(type_die, "alloc error");
                        CLEANUP_AND_RETURN_ERROR(NULL);
                }
-               dict_insert(type_dieoffset_hash, &die_offset, &result);
+               DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
                pointee = get_type(&newly_allocated_pointee,
                                   &next_die, plib, type_dieoffset_hash);
                if (pointee == NULL)
@@ -746,7 +768,7 @@ static struct arg_type_info *get_type(int *newly_allocated_result,
                        result = type_get_simple(ARGTYPE_VOID);
                        complain(type_die, "Storing void type");
                }
-               dict_insert(type_dieoffset_hash, &die_offset, &result);
+               DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
                return result;
 
        case DW_TAG_enumeration_type:
@@ -772,17 +794,18 @@ static struct arg_type_info *get_type(int *newly_allocated_result,
        case DW_TAG_union_type:
                result = type_get_simple(ARGTYPE_VOID);
                complain(type_die, "Storing union-as-void type");
-               dict_insert(type_dieoffset_hash, &die_offset, &result);
+               DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
                return result;
 
        default:
                complain(type_die, "Unknown type tag 0x%x. Returning void",
                         dwarf_tag(type_die));
                result = type_get_simple(ARGTYPE_VOID);
-               dict_insert(type_dieoffset_hash, &die_offset, &result);
+               DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result);
                return result;
        }
 
+#undef DICT_INSERT_AND_CHECK
 #undef CLEANUP_AND_RETURN_ERROR
 }
 
@@ -881,23 +904,10 @@ static bool get_prototype(struct prototype *result,
 #undef CLEANUP_AND_RETURN_ERROR
 }
 
-static bool import_subprogram(struct protolib *plib, struct library *lib,
-                             struct dict *type_dieoffset_hash,
-                             Dwarf_Die *die)
+static bool import_subprogram_name(struct protolib *plib, struct library *lib,
+                                  struct dict *type_dieoffset_hash,
+                                  Dwarf_Die *die, const char* function_name)
 {
-       // I use the linkage function name if there is one, otherwise the
-       // plain name
-       const char *function_name = NULL;
-       Dwarf_Attribute attr;
-       if (dwarf_attr(die, DW_AT_linkage_name, &attr) != NULL)
-               function_name = dwarf_formstring(&attr);
-       if (function_name == NULL)
-               function_name = dwarf_diename(die);
-       if (function_name == NULL) {
-               complain(die, "Function has no name. Not importing");
-               return true;
-       }
-
        if (!filter_matches_symbol(options.plt_filter,    function_name, lib) &&
            !filter_matches_symbol(options.static_filter, function_name, lib) &&
            !filter_matches_symbol(options.export_filter, function_name, lib)) {
@@ -932,6 +942,36 @@ static bool import_subprogram(struct protolib *plib, struct library *lib,
        return true;
 }
 
+static bool import_subprogram_die(struct protolib *plib, struct library *lib,
+                                 struct dict *type_dieoffset_hash,
+                                 Dwarf_Die *die)
+{
+       // If there is a linkage name, I use it (this is required for C++ code,
+       // in particular).
+       //
+       // I use the plain name regardless, since sometimes the exported symbol
+       // corresponds to the plain name, NOT the linkage name. For instance I
+       // see this on my Debian/sid amd64 box. In its libc, the linkage name of
+       // __nanosleep is __GI___nanosleep, but the export is __nanosleep
+       const char *function_name;
+       Dwarf_Attribute attr;
+
+       if (dwarf_attr(die, DW_AT_linkage_name, &attr) != NULL &&
+           (function_name = dwarf_formstring(&attr)) != NULL &&
+           !import_subprogram_name(plib, lib, type_dieoffset_hash, die,
+                                   function_name)) {
+               return false;
+       }
+
+       if ((function_name = dwarf_diename(die)) != NULL &&
+           !import_subprogram_name(plib, lib, type_dieoffset_hash, die,
+                                   function_name)) {
+               return false;
+       }
+
+       return true;
+}
+
 static bool process_die_compileunit(struct protolib *plib, struct library *lib,
                                    struct dict *type_dieoffset_hash,
                                    Dwarf_Die *parent)
@@ -945,8 +985,8 @@ static bool process_die_compileunit(struct protolib *plib, struct library *lib,
 
        while (1) {
                if (dwarf_tag(&die) == DW_TAG_subprogram)
-                       if (!import_subprogram(plib, lib, type_dieoffset_hash,
-                                              &die))
+                       if (!import_subprogram_die(plib, lib, type_dieoffset_hash,
+                                                  &die))
                                complain(&die, "Error importing subprogram. "
                                         "Skipping");
 
@@ -956,7 +996,8 @@ static bool process_die_compileunit(struct protolib *plib, struct library *lib,
        return true;
 }
 
-static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl)
+static void import(struct protolib *plib, struct library *lib,
+                  Dwfl_Module *dwfl_module)
 {
        // A map from DIE addresses (Dwarf_Off) to type structures (struct
        // arg_type_info*). This is created and filled in at the start of each
@@ -969,7 +1010,7 @@ static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl)
 
        Dwarf_Addr bias;
        Dwarf_Die *die = NULL;
-       while ((die = dwfl_nextcu(dwfl, die, &bias)) != NULL) {
+       while ((die = dwfl_module_nextcu(dwfl_module, die, &bias)) != NULL) {
                if (dwarf_tag(die) == DW_TAG_compile_unit)
                        process_die_compileunit(plib, lib,
                                                &type_dieoffset_hash, die);
@@ -984,7 +1025,6 @@ static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl)
 bool import_DWARF_prototypes(struct library *lib)
 {
        struct protolib *plib = lib->protolib;
-       Dwfl *dwfl = lib->dwfl;
 
        debug(DEBUG_FUNCTION, "Importing DWARF prototypes from '%s'",
              lib->soname);
@@ -1003,7 +1043,7 @@ bool import_DWARF_prototypes(struct library *lib)
                }
        }
 
-       import(plib, lib, dwfl);
+       import(plib, lib, lib->dwfl_module);
        lib->protolib = plib;
 
        return true;