changeset 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 fbdb7686a9e9
children 25d3ead621f8
files leo-obj/tool/Makefile leo-obj/tool/coffconst.h leo-obj/tool/intstruct.h leo-obj/tool/richsym.c leo-obj/tool/tables.c
diffstat 5 files changed, 214 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/leo-obj/tool/Makefile	Mon Apr 28 05:55:40 2014 +0000
+++ b/leo-obj/tool/Makefile	Mon Apr 28 08:04:39 2014 +0000
@@ -2,7 +2,7 @@
 CFLAGS=	-O2
 PROG=	tiobjd
 OBJS=	armdis.o atcommon.o basics.o disasm.o globals.o hints.o ln.o lowlevel.o\
-	main.o profile.o reloc.o symtab.o tables.o thumbdis.o
+	main.o profile.o reloc.o richsym.o symtab.o tables.o thumbdis.o
 HDRS=	coffconst.h filestruct.h globals.h intstruct.h
 
 all:	${PROG}
--- a/leo-obj/tool/coffconst.h	Mon Apr 28 05:55:40 2014 +0000
+++ b/leo-obj/tool/coffconst.h	Mon Apr 28 08:04:39 2014 +0000
@@ -30,6 +30,31 @@
 #define C_FILE		103	/* file name			*/
 #define C_LINE		104	/* line # reformatted as symbol table entry */
 
+/* Type of a symbol, in low 4 bits of the word.  */
+
+#define T_VOID		0	/* seen in void ptrs in our objects */
+#define T_CHAR		2	/* character		*/
+#define T_SHORT		3	/* short integer	*/
+#define T_INT		4	/* integer		*/
+#define T_LONG		5	/* long integer		*/
+#define T_FLOAT		6	/* floating point	*/
+#define T_DOUBLE	7	/* double word		*/
+#define T_STRUCT	8	/* structure 		*/
+#define T_UNION		9	/* union 		*/
+#define T_ENUM		10	/* enumeration 		*/
+#define T_MOE		11	/* member of enumeration*/
+#define T_UCHAR		12	/* unsigned character	*/
+#define T_USHORT	13	/* unsigned short	*/
+#define T_UINT		14	/* unsigned integer	*/
+#define T_ULONG		15	/* unsigned long	*/
+
+/* Derived types, in n_type.  */
+
+#define DT_NON		0	/* no derived type */
+#define DT_PTR		1	/* pointer */
+#define DT_FCN		2	/* function */
+#define DT_ARY		3	/* array */
+
 /* Reloc types */
 
 #define	RTYPE_LONG	0x11
--- a/leo-obj/tool/intstruct.h	Mon Apr 28 05:55:40 2014 +0000
+++ b/leo-obj/tool/intstruct.h	Mon Apr 28 08:04:39 2014 +0000
@@ -33,6 +33,8 @@
 	int		class;
 	u_char		*aux;
 	struct internal_scnhdr *section;
+	char		*struct_name;
+	char		*struct_name_raw;
 };
 
 struct internal_reloc {
--- /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");
+	}
+}
--- a/leo-obj/tool/tables.c	Mon Apr 28 05:55:40 2014 +0000
+++ b/leo-obj/tool/tables.c	Mon Apr 28 08:04:39 2014 +0000
@@ -131,6 +131,8 @@
 			in->section = 0;
 		in->type = get_u16(symtab_raw[n].e_type);
 		in->class = symtab_raw[n].e_sclass;
+		in->struct_name = 0;
+		in->struct_name_raw = 0;
 		switch (symtab_raw[n++].e_numaux) {
 		case 0:
 			in->aux = 0;