FreeCalypso > hg > freecalypso-reveng
diff leo-obj/tool/richsym.c @ 144:fd772de226cb
tiobjd: started implementing rich symbolic info parsing
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Mon, 28 Apr 2014 08:04:39 +0000 |
parents | |
children | 25d3ead621f8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/richsym.c Mon Apr 28 08:04:39 2014 +0000 @@ -0,0 +1,184 @@ +/* + * Code for working with the "rich" symbolic info + * present in TI's GPF libraries + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "intstruct.h" +#include "coffconst.h" +#include "globals.h" + +extern unsigned get_u16(), get_u32(); +extern char *storage_class_to_string(); + +static int +try_typedef_hack(struct_sym) + struct internal_syment *struct_sym; +{ + unsigned tpdef_cand; + struct internal_syment *tpdef_sym; + + if (!struct_sym->aux) + return(0); + tpdef_cand = get_u32(struct_sym->aux + 12); + if (tpdef_cand >= nsymtab) + return(0); + tpdef_sym = symtab[tpdef_cand]; + if (!tpdef_sym) + return(0); + if (tpdef_sym->class != C_TPDEF) + return(0); + if (tpdef_sym->type != struct_sym->type) + return(0); + if (tpdef_sym->name[0] != '_') + return(0); + if (!tpdef_sym->aux) + return(0); + if (get_u32(tpdef_sym->aux) != struct_sym->number) + return(0); + struct_sym->struct_name = tpdef_sym->name + 1; + return(1); +} + +static void +preen_strtag_sym(sym, kw, expect_type) + struct internal_syment *sym; + char *kw; +{ + char *buf; + int isund, len; + + isund = (sym->name[0] == '_'); + len = strlen(kw) + 1 + strlen(sym->name) + 1; + if (isund) + len--; + else + len += 2; + buf = malloc(len); + if (!buf) { + perror("malloc"); + exit(1); + } + if (isund) + sprintf(buf, "%s %s", kw, sym->name + 1); + else + sprintf(buf, "%s \"%s\"", kw, sym->name); + sym->struct_name = buf; + sym->struct_name_raw = buf; + if (sym->type != expect_type) { + fprintf(stderr, + "warning: type/class mismatch on tag symbol #%u\n", + sym->number); + return; + } + if (isund) + return; + try_typedef_hack(sym); +} + +richsym_initial_preen() +{ + unsigned n; + struct internal_syment *sym; + + for (n = 0; n < nsymtab; n++) { + sym = symtab[n]; + if (!sym) + continue; + switch (sym->class) { + case C_STRTAG: + preen_strtag_sym(sym, "struct", T_STRUCT); + continue; + case C_UNTAG: + preen_strtag_sym(sym, "union", T_UNION); + continue; + case C_ENTAG: + preen_strtag_sym(sym, "enum", T_ENUM); + continue; + } + } +} + +char * +get_struct_type_name(idx, expect_class, is_typedef) + unsigned idx; +{ + struct internal_syment *sym; + + if (idx >= nsymtab) { +inv_idx: fprintf(stderr, + "error: ref to invalid syment #%u for struct tag\n", + idx); + exit(1); + } + sym = symtab[idx]; + if (!sym) + goto inv_idx; + if (sym->class != expect_class) { + fprintf(stderr, + "error: ref to syment #%u for struct tag, class != %s\n", + idx, storage_class_to_string(expect_class, 0)); + exit(1); + } + if (is_typedef) + return(sym->struct_name_raw); + else + return(sym->struct_name); +} + +char * +get_base_type_of_syment(sym, is_typedef) + struct internal_syment *sym; +{ + switch (sym->type & 0xF) { + case T_VOID: + return("void"); + case T_CHAR: + if (is_typedef) + return("signed char"); + else + return("char"); + case T_SHORT: + return("short"); + case T_INT: + return("int"); + case T_LONG: + return("long"); + case T_FLOAT: + return("float"); + case T_DOUBLE: + return("double"); + case T_STRUCT: + return get_struct_type_name(get_u32(sym->aux), C_STRTAG, + is_typedef); + case T_UNION: + return get_struct_type_name(get_u32(sym->aux), C_UNTAG, + is_typedef); + case T_ENUM: + return get_struct_type_name(get_u32(sym->aux), C_ENTAG, + is_typedef); + case T_UCHAR: + if (is_typedef) + return("unsigned char"); + else + return("u_char"); + case T_USHORT: + if (is_typedef) + return("unsigned short"); + else + return("u_short"); + case T_UINT: + return("unsigned"); + case T_ULONG: + if (is_typedef) + return("unsigned long"); + else + return("u_long"); + default: + return("__unknown_base_type"); + } +}