Drop uses of #pragma once
[platform/upstream/ltrace.git] / dwarf_prototypes.c
index 25390e2..9c36904 100644 (file)
@@ -94,7 +94,7 @@ static bool _dump_ltrace_tree(const struct arg_type_info *info, int indent)
                {
                        struct arg_type_info *info;
                        int own_info;
-               }elements = (struct struct_field*)info->u.entries.data;
+               } *elements = (struct struct_field*)info->u.entries.data;
                unsigned int i;
                for(i=0; i<info->u.entries.size; i++)
                        _dump_ltrace_tree(elements[i].info, indent+1);
@@ -171,34 +171,37 @@ static bool get_die_numeric(uint64_t *result,
 static bool get_integer_base_type(enum arg_type *type, int byte_size,
                                  bool is_signed)
 {
-       switch (byte_size) {
-       case sizeof(char):
+       // not using a switch() here because sizeof(int) == sizeof(long) on some
+       // architectures, and removing that case for those arches is a pain
+       if (byte_size == sizeof(char)) {
                *type = ARGTYPE_CHAR;
                return true;
+       }
 
-       case sizeof(short):
+       if (byte_size == sizeof(short)) {
                *type = is_signed ? ARGTYPE_SHORT : ARGTYPE_USHORT;
                return true;
+       }
 
-       case sizeof(int):
+       if (byte_size == sizeof(int)) {
                *type = is_signed ? ARGTYPE_INT : ARGTYPE_UINT;
                return true;
+       }
 
-       case sizeof(long):
+       if (byte_size == sizeof(long)) {
                *type = is_signed ? ARGTYPE_LONG : ARGTYPE_ULONG;
                return true;
-
-       default:
-               return false;
        }
+
+       return false;
 }
 
 // returns an ltrace ARGTYPE_XXX base type from the given die. If we dont
 // support a particular type (or an error occurred), I regturn ARGTYPE_VOID
 static enum arg_type get_base_type(Dwarf_Die *die)
 {
-       int64_t encoding;
-       if (!get_die_numeric((uint64_t*)&encoding, die, DW_AT_encoding))
+       uint64_t encoding;
+       if (!get_die_numeric(&encoding, die, DW_AT_encoding))
                return ARGTYPE_VOID;
 
        if (encoding == DW_ATE_void)
@@ -296,7 +299,7 @@ static struct arg_type_info *get_enum(Dwarf_Die *parent,
                        value_destroy(value);                           \
                        free(value);                                    \
                }                                                       \
-               if (lens != NULL ) {                                    \
+               if (lens != NULL) {                                     \
                        lens_destroy(&lens->super);                     \
                        free(lens);                                     \
                }                                                       \
@@ -312,10 +315,10 @@ static struct arg_type_info *get_enum(Dwarf_Die *parent,
                return ret;                                             \
        } while (0)
 
-       struct arg_type_inforesult = NULL;
-       struct enum_lenslens = NULL;
-       const chardupkey = NULL;
-       struct valuevalue = NULL;
+       struct arg_type_info *result = NULL;
+       struct enum_lens *lens = NULL;
+       const char *dupkey = NULL;
+       struct value *value = NULL;
 
        Dwarf_Off die_offset = dwarf_dieoffset(parent);
 
@@ -325,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)) {
@@ -416,9 +422,9 @@ static struct arg_type_info *get_enum(Dwarf_Die *parent,
 }
 
 // returns a newly-allocated art_type_info*, or NULL on error
-static struct arg_type_info *get_array( Dwarf_Die *parent,
-                                       struct protolib *plib,
-                                       struct dict *type_dieoffset_hash)
+static struct arg_type_info *get_array(Dwarf_Die *parent,
+                                      struct protolib *plib,
+                                      struct dict *type_dieoffset_hash)
 {
 
 #define CLEANUP_AND_RETURN_ERROR(ret) do {                             \
@@ -443,9 +449,9 @@ static struct arg_type_info *get_array( Dwarf_Die *parent,
        } while (0)
 
 
-       struct arg_type_inforesult = NULL;
-       struct expr_nodelength = NULL;
-       struct arg_type_infoarray_type = NULL;
+       struct arg_type_info *result = NULL;
+       struct expr_node *length = NULL;
+       struct arg_type_info *array_type = NULL;
        int newly_allocated_array_type = 0;
 
        Dwarf_Off die_offset = dwarf_dieoffset(parent);
@@ -462,10 +468,13 @@ 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 ) {
+       if (array_type == NULL) {
                complain(parent, "Couldn't figure out array's type");
                CLEANUP_AND_RETURN_ERROR(NULL);
        }
@@ -559,8 +568,8 @@ static struct arg_type_info *get_structure(Dwarf_Die *parent,
        } while (0)
 
 
-       struct arg_type_inforesult = NULL;
-       struct arg_type_infomember_type = NULL;
+       struct arg_type_info *result = NULL;
+       struct arg_type_info *member_type = NULL;
        int newly_allocated_member_type = 0;
 
        Dwarf_Off die_offset = dwarf_dieoffset(parent);
@@ -571,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) {
@@ -602,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);
        }
@@ -638,8 +653,18 @@ static struct arg_type_info *get_type(int *newly_allocated_result,
                return ret;                                             \
        } while (0)
 
-       struct arg_type_info* result = NULL;
-       struct arg_type_info* pointee = NULL;
+#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;
 
        Dwarf_Off die_offset = dwarf_dieoffset(type_die);
@@ -677,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:
@@ -686,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:
@@ -695,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;
                }
 
@@ -707,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)
@@ -743,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:
@@ -769,24 +794,25 @@ 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
 }
 
 // fills in *proto with a prototype. Returns true on success
-static bool get_prototype( struct prototype *result,
-                          Dwarf_Die *subroutine, struct protolib *plib,
-                          struct dict *type_dieoffset_hash)
+static bool get_prototype(struct prototype *result,
+                         Dwarf_Die *subroutine, struct protolib *plib,
+                         struct dict *type_dieoffset_hash)
 {
 
 #define CLEANUP_AND_RETURN_ERROR(ret) do {                             \
@@ -799,7 +825,7 @@ static bool get_prototype( struct prototype *result,
        } while (0)
 
 
-       struct arg_type_infoargument_type = NULL;
+       struct arg_type_info *argument_type = NULL;
        int newly_allocated_argument_type = 0;
 
        prototype_init(result);
@@ -878,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)) {
@@ -920,7 +933,7 @@ static bool import_subprogram(struct protolib *plib, struct library *lib,
        }
 
        const char *function_name_dup = strdup(function_name);
-       if ( function_name_dup == NULL ) {
+       if (function_name_dup == NULL) {
                complain(die, "couldn't strdup");
                prototype_destroy(&proto);
                return false;
@@ -929,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)
@@ -942,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");
 
@@ -953,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
@@ -966,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);
@@ -980,15 +1024,14 @@ 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;
+       struct protolib *plib = lib->protolib;
 
        debug(DEBUG_FUNCTION, "Importing DWARF prototypes from '%s'",
              lib->soname);
        if (plib == NULL) {
 
                const char *soname_dup = strdup(lib->soname);
-               if ( soname_dup == NULL ) {
+               if (soname_dup == NULL) {
                        fprintf(stderr, "couldn't strdup");
                        return false;
                }
@@ -1000,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;