diff src/gba/elf.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/gba/elf.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,3229 @@
     1.4 +#include <cstdio>
     1.5 +#include <cstdlib>
     1.6 +#include <cstring>
     1.7 +
     1.8 +#include "../Port.h"
     1.9 +#include "../NLS.h"
    1.10 +#include "../common/System.h" // systemMessage
    1.11 +#include "GBAGlobals.h"
    1.12 +#include "elf.h"
    1.13 +
    1.14 +#define elfReadMemory(addr) \
    1.15 +    READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
    1.16 +
    1.17 +#define DW_TAG_array_type             0x01
    1.18 +#define DW_TAG_enumeration_type       0x04
    1.19 +#define DW_TAG_formal_parameter       0x05
    1.20 +#define DW_TAG_label                  0x0a
    1.21 +#define DW_TAG_lexical_block          0x0b
    1.22 +#define DW_TAG_member                 0x0d
    1.23 +#define DW_TAG_pointer_type           0x0f
    1.24 +#define DW_TAG_reference_type         0x10
    1.25 +#define DW_TAG_compile_unit           0x11
    1.26 +#define DW_TAG_structure_type         0x13
    1.27 +#define DW_TAG_subroutine_type        0x15
    1.28 +#define DW_TAG_typedef                0x16
    1.29 +#define DW_TAG_union_type             0x17
    1.30 +#define DW_TAG_unspecified_parameters 0x18
    1.31 +#define DW_TAG_inheritance            0x1c
    1.32 +#define DW_TAG_inlined_subroutine     0x1d
    1.33 +#define DW_TAG_subrange_type          0x21
    1.34 +#define DW_TAG_base_type              0x24
    1.35 +#define DW_TAG_const_type             0x26
    1.36 +#define DW_TAG_enumerator             0x28
    1.37 +#define DW_TAG_subprogram             0x2e
    1.38 +#define DW_TAG_variable               0x34
    1.39 +#define DW_TAG_volatile_type          0x35
    1.40 +
    1.41 +#define DW_AT_sibling              0x01
    1.42 +#define DW_AT_location             0x02
    1.43 +#define DW_AT_name                 0x03
    1.44 +#define DW_AT_byte_size            0x0b
    1.45 +#define DW_AT_bit_offset           0x0c
    1.46 +#define DW_AT_bit_size             0x0d
    1.47 +#define DW_AT_stmt_list            0x10
    1.48 +#define DW_AT_low_pc               0x11
    1.49 +#define DW_AT_high_pc              0x12
    1.50 +#define DW_AT_language             0x13
    1.51 +#define DW_AT_compdir              0x1b
    1.52 +#define DW_AT_const_value          0x1c
    1.53 +#define DW_AT_containing_type      0x1d
    1.54 +#define DW_AT_inline               0x20
    1.55 +#define DW_AT_producer             0x25
    1.56 +#define DW_AT_prototyped           0x27
    1.57 +#define DW_AT_upper_bound          0x2f
    1.58 +#define DW_AT_abstract_origin      0x31
    1.59 +#define DW_AT_accessibility        0x32
    1.60 +#define DW_AT_artificial           0x34
    1.61 +#define DW_AT_data_member_location 0x38
    1.62 +#define DW_AT_decl_file            0x3a
    1.63 +#define DW_AT_decl_line            0x3b
    1.64 +#define DW_AT_declaration          0x3c
    1.65 +#define DW_AT_encoding             0x3e
    1.66 +#define DW_AT_external             0x3f
    1.67 +#define DW_AT_frame_base           0x40
    1.68 +#define DW_AT_macro_info           0x43
    1.69 +#define DW_AT_specification        0x47
    1.70 +#define DW_AT_type                 0x49
    1.71 +#define DW_AT_virtuality           0x4c
    1.72 +#define DW_AT_vtable_elem_location 0x4d
    1.73 +// DWARF 2.1/3.0 extensions
    1.74 +#define DW_AT_entry_pc             0x52
    1.75 +#define DW_AT_ranges               0x55
    1.76 +// ARM Compiler extensions
    1.77 +#define DW_AT_proc_body            0x2000
    1.78 +#define DW_AT_save_offset          0x2001
    1.79 +#define DW_AT_user_2002            0x2002
    1.80 +// MIPS extensions
    1.81 +#define DW_AT_MIPS_linkage_name    0x2007
    1.82 +
    1.83 +#define DW_FORM_addr      0x01
    1.84 +#define DW_FORM_data2     0x05
    1.85 +#define DW_FORM_data4     0x06
    1.86 +#define DW_FORM_string    0x08
    1.87 +#define DW_FORM_block     0x09
    1.88 +#define DW_FORM_block1    0x0a
    1.89 +#define DW_FORM_data1     0x0b
    1.90 +#define DW_FORM_flag      0x0c
    1.91 +#define DW_FORM_sdata     0x0d
    1.92 +#define DW_FORM_strp      0x0e
    1.93 +#define DW_FORM_udata     0x0f
    1.94 +#define DW_FORM_ref_addr  0x10
    1.95 +#define DW_FORM_ref4      0x13
    1.96 +#define DW_FORM_ref_udata 0x15
    1.97 +#define DW_FORM_indirect  0x16
    1.98 +
    1.99 +#define DW_OP_addr        0x03
   1.100 +#define DW_OP_plus_uconst 0x23
   1.101 +#define DW_OP_reg0        0x50
   1.102 +#define DW_OP_reg1        0x51
   1.103 +#define DW_OP_reg2        0x52
   1.104 +#define DW_OP_reg3        0x53
   1.105 +#define DW_OP_reg4        0x54
   1.106 +#define DW_OP_reg5        0x55
   1.107 +#define DW_OP_reg6        0x56
   1.108 +#define DW_OP_reg7        0x57
   1.109 +#define DW_OP_reg8        0x58
   1.110 +#define DW_OP_reg9        0x59
   1.111 +#define DW_OP_reg10       0x5a
   1.112 +#define DW_OP_reg11       0x5b
   1.113 +#define DW_OP_reg12       0x5c
   1.114 +#define DW_OP_reg13       0x5d
   1.115 +#define DW_OP_reg14       0x5e
   1.116 +#define DW_OP_reg15       0x5f
   1.117 +#define DW_OP_fbreg       0x91
   1.118 +
   1.119 +#define DW_LNS_extended_op      0x00
   1.120 +#define DW_LNS_copy             0x01
   1.121 +#define DW_LNS_advance_pc       0x02
   1.122 +#define DW_LNS_advance_line     0x03
   1.123 +#define DW_LNS_set_file         0x04
   1.124 +#define DW_LNS_set_column       0x05
   1.125 +#define DW_LNS_negate_stmt      0x06
   1.126 +#define DW_LNS_set_basic_block  0x07
   1.127 +#define DW_LNS_const_add_pc     0x08
   1.128 +#define DW_LNS_fixed_advance_pc 0x09
   1.129 +
   1.130 +#define DW_LNE_end_sequence 0x01
   1.131 +#define DW_LNE_set_address  0x02
   1.132 +#define DW_LNE_define_file  0x03
   1.133 +
   1.134 +#define DW_CFA_advance_loc      0x01
   1.135 +#define DW_CFA_offset           0x02
   1.136 +#define DW_CFA_restore          0x03
   1.137 +#define DW_CFA_set_loc          0x01
   1.138 +#define DW_CFA_advance_loc1     0x02
   1.139 +#define DW_CFA_advance_loc2     0x03
   1.140 +#define DW_CFA_advance_loc4     0x04
   1.141 +#define DW_CFA_offset_extended  0x05
   1.142 +#define DW_CFA_restore_extended 0x06
   1.143 +#define DW_CFA_undefined        0x07
   1.144 +#define DW_CFA_same_value       0x08
   1.145 +#define DW_CFA_register         0x09
   1.146 +#define DW_CFA_remember_state   0x0a
   1.147 +#define DW_CFA_restore_state    0x0b
   1.148 +#define DW_CFA_def_cfa          0x0c
   1.149 +#define DW_CFA_def_cfa_register 0x0d
   1.150 +#define DW_CFA_def_cfa_offset   0x0e
   1.151 +#define DW_CFA_nop              0x00
   1.152 +
   1.153 +#define CASE_TYPE_TAG \
   1.154 +case DW_TAG_const_type: \
   1.155 +case DW_TAG_volatile_type: \
   1.156 +case DW_TAG_pointer_type: \
   1.157 +case DW_TAG_base_type: \
   1.158 +case DW_TAG_array_type: \
   1.159 +case DW_TAG_structure_type: \
   1.160 +case DW_TAG_union_type: \
   1.161 +case DW_TAG_typedef: \
   1.162 +case DW_TAG_subroutine_type: \
   1.163 +case DW_TAG_enumeration_type: \
   1.164 +case DW_TAG_enumerator: \
   1.165 +case DW_TAG_reference_type
   1.166 +
   1.167 +struct ELFcie
   1.168 +{
   1.169 +	ELFcie *next;
   1.170 +	u32     offset;
   1.171 +	u8 *    augmentation;
   1.172 +	u32     codeAlign;
   1.173 +	s32     dataAlign;
   1.174 +	int     returnAddress;
   1.175 +	u8 *    data;
   1.176 +	u32     dataLen;
   1.177 +};
   1.178 +
   1.179 +struct ELFfde
   1.180 +{
   1.181 +	ELFcie *cie;
   1.182 +	u32     address;
   1.183 +	u32     end;
   1.184 +	u8 *    data;
   1.185 +	u32     dataLen;
   1.186 +};
   1.187 +
   1.188 +enum ELFRegMode
   1.189 +{
   1.190 +	REG_NOT_SET,
   1.191 +	REG_OFFSET,
   1.192 +	REG_REGISTER
   1.193 +};
   1.194 +
   1.195 +struct ELFFrameStateRegister
   1.196 +{
   1.197 +	ELFRegMode mode;
   1.198 +	int        reg;
   1.199 +	s32        offset;
   1.200 +};
   1.201 +
   1.202 +struct ELFFrameStateRegisters
   1.203 +{
   1.204 +	ELFFrameStateRegister   regs[16];
   1.205 +	ELFFrameStateRegisters *previous;
   1.206 +};
   1.207 +
   1.208 +enum ELFCfaMode
   1.209 +{
   1.210 +	CFA_NOT_SET,
   1.211 +	CFA_REG_OFFSET
   1.212 +};
   1.213 +
   1.214 +struct ELFFrameState
   1.215 +{
   1.216 +	ELFFrameStateRegisters registers;
   1.217 +
   1.218 +	ELFCfaMode cfaMode;
   1.219 +	int        cfaRegister;
   1.220 +	s32        cfaOffset;
   1.221 +
   1.222 +	u32 pc;
   1.223 +
   1.224 +	int dataAlign;
   1.225 +	int codeAlign;
   1.226 +	int returnAddress;
   1.227 +};
   1.228 +
   1.229 +extern bool8 cpuIsMultiBoot;
   1.230 +
   1.231 +Symbol *elfSymbols       = NULL;
   1.232 +char *  elfSymbolsStrTab = NULL;
   1.233 +int     elfSymbolsCount  = 0;
   1.234 +
   1.235 +ELFSectionHeader **elfSectionHeaders = NULL;
   1.236 +char *elfSectionHeadersStringTable   = NULL;
   1.237 +int   elfSectionHeadersCount         = 0;
   1.238 +u8 *  elfFileData = NULL;
   1.239 +
   1.240 +CompileUnit *elfCompileUnits = NULL;
   1.241 +DebugInfo *  elfDebugInfo    = NULL;
   1.242 +char *       elfDebugStrings = NULL;
   1.243 +
   1.244 +ELFcie * elfCies     = NULL;
   1.245 +ELFfde **elfFdes     = NULL;
   1.246 +int      elfFdeCount = 0;
   1.247 +
   1.248 +CompileUnit *elfCurrentUnit = NULL;
   1.249 +
   1.250 +u32 elfRead4Bytes(u8 *);
   1.251 +u16 elfRead2Bytes(u8 *);
   1.252 +
   1.253 +CompileUnit *elfGetCompileUnit(u32 addr)
   1.254 +{
   1.255 +	if (elfCompileUnits)
   1.256 +	{
   1.257 +		CompileUnit *unit = elfCompileUnits;
   1.258 +		while (unit)
   1.259 +		{
   1.260 +			if (unit->lowPC)
   1.261 +			{
   1.262 +				if (addr >= unit->lowPC && addr < unit->highPC)
   1.263 +					return unit;
   1.264 +			}
   1.265 +			else
   1.266 +			{
   1.267 +				ARanges *r = unit->ranges;
   1.268 +				if (r)
   1.269 +				{
   1.270 +					int count = r->count;
   1.271 +					for (int j = 0; j < count; j++)
   1.272 +					{
   1.273 +						if (addr >= r->ranges[j].lowPC && addr < r->ranges[j].highPC)
   1.274 +							return unit;
   1.275 +					}
   1.276 +				}
   1.277 +			}
   1.278 +			unit = unit->next;
   1.279 +		}
   1.280 +	}
   1.281 +	return NULL;
   1.282 +}
   1.283 +
   1.284 +char *elfGetAddressSymbol(u32 addr)
   1.285 +{
   1.286 +	static char buffer[256];
   1.287 +
   1.288 +	CompileUnit *unit = elfGetCompileUnit(addr);
   1.289 +	// found unit, need to find function
   1.290 +	if (unit)
   1.291 +	{
   1.292 +		Function *func = unit->functions;
   1.293 +		while (func)
   1.294 +		{
   1.295 +			if (addr >= func->lowPC && addr < func->highPC)
   1.296 +			{
   1.297 +				int   offset = addr - func->lowPC;
   1.298 +				char *name   = func->name;
   1.299 +				if (!name)
   1.300 +					name = "";
   1.301 +				if (offset)
   1.302 +					sprintf(buffer, "%s+%d", name, offset);
   1.303 +				else
   1.304 +					strcpy(buffer, name);
   1.305 +				return buffer;
   1.306 +			}
   1.307 +			func = func->next;
   1.308 +		}
   1.309 +	}
   1.310 +
   1.311 +	if (elfSymbolsCount)
   1.312 +	{
   1.313 +		for (int i = 0; i < elfSymbolsCount; i++)
   1.314 +		{
   1.315 +			Symbol *s = &elfSymbols[i];
   1.316 +			if ((addr >= s->value)  && addr < (s->value+s->size))
   1.317 +			{
   1.318 +				int   offset = addr-s->value;
   1.319 +				char *name   = s->name;
   1.320 +				if (name == NULL)
   1.321 +					name = "";
   1.322 +				if (offset)
   1.323 +					sprintf(buffer, "%s+%d", name, addr-s->value);
   1.324 +				else
   1.325 +					strcpy(buffer, name);
   1.326 +				return buffer;
   1.327 +			}
   1.328 +			else if (addr == s->value)
   1.329 +			{
   1.330 +				if (s->name)
   1.331 +					strcpy(buffer, s->name);
   1.332 +				else
   1.333 +					strcpy(buffer, "");
   1.334 +				return buffer;
   1.335 +			}
   1.336 +		}
   1.337 +	}
   1.338 +
   1.339 +	return "";
   1.340 +}
   1.341 +
   1.342 +bool elfFindLineInModule(u32 *addr, char *name, int line)
   1.343 +{
   1.344 +	CompileUnit *unit = elfCompileUnits;
   1.345 +
   1.346 +	while (unit)
   1.347 +	{
   1.348 +		if (unit->lineInfoTable)
   1.349 +		{
   1.350 +			int   i;
   1.351 +			int   count = unit->lineInfoTable->fileCount;
   1.352 +			char *found = NULL;
   1.353 +			for (i = 0; i < count; i++)
   1.354 +			{
   1.355 +				if (strcmp(name, unit->lineInfoTable->files[i]) == 0)
   1.356 +				{
   1.357 +					found = unit->lineInfoTable->files[i];
   1.358 +					break;
   1.359 +				}
   1.360 +			}
   1.361 +			// found a matching filename... try to find line now
   1.362 +			if (found)
   1.363 +			{
   1.364 +				LineInfoItem *table = unit->lineInfoTable->lines;
   1.365 +				count = unit->lineInfoTable->number;
   1.366 +				for (i = 0; i < count; i++)
   1.367 +				{
   1.368 +					if (table[i].file == found && table[i].line == line)
   1.369 +					{
   1.370 +						*addr = table[i].address;
   1.371 +						return true;
   1.372 +					}
   1.373 +				}
   1.374 +				// we can only find a single match
   1.375 +				return false;
   1.376 +			}
   1.377 +		}
   1.378 +		unit = unit->next;
   1.379 +	}
   1.380 +	return false;
   1.381 +}
   1.382 +
   1.383 +int elfFindLine(CompileUnit *unit, Function * /* func */, u32 addr, char **f)
   1.384 +{
   1.385 +	int currentLine = -1;
   1.386 +	if (unit->hasLineInfo)
   1.387 +	{
   1.388 +		int count = unit->lineInfoTable->number;
   1.389 +		LineInfoItem *table = unit->lineInfoTable->lines;
   1.390 +		int i;
   1.391 +		for (i = 0; i < count; i++)
   1.392 +		{
   1.393 +			if (addr <= table[i].address)
   1.394 +				break;
   1.395 +		}
   1.396 +		if (i == count)
   1.397 +			i--;
   1.398 +		*f = table[i].file;
   1.399 +		currentLine = table[i].line;
   1.400 +	}
   1.401 +	return currentLine;
   1.402 +}
   1.403 +
   1.404 +bool elfFindLineInUnit(u32 *addr, CompileUnit *unit, int line)
   1.405 +{
   1.406 +	if (unit->hasLineInfo)
   1.407 +	{
   1.408 +		int count = unit->lineInfoTable->number;
   1.409 +		LineInfoItem *table = unit->lineInfoTable->lines;
   1.410 +		int i;
   1.411 +		for (i = 0; i < count; i++)
   1.412 +		{
   1.413 +			if (line == table[i].line)
   1.414 +			{
   1.415 +				*addr = table[i].address;
   1.416 +				return true;
   1.417 +			}
   1.418 +		}
   1.419 +	}
   1.420 +	return false;
   1.421 +}
   1.422 +
   1.423 +bool elfGetCurrentFunction(u32 addr, Function **f, CompileUnit **u)
   1.424 +{
   1.425 +	CompileUnit *unit = elfGetCompileUnit(addr);
   1.426 +	// found unit, need to find function
   1.427 +	if (unit)
   1.428 +	{
   1.429 +		Function *func = unit->functions;
   1.430 +		while (func)
   1.431 +		{
   1.432 +			if (addr >= func->lowPC && addr < func->highPC)
   1.433 +			{
   1.434 +				*f = func;
   1.435 +				*u = unit;
   1.436 +				return true;
   1.437 +			}
   1.438 +			func = func->next;
   1.439 +		}
   1.440 +	}
   1.441 +	return false;
   1.442 +}
   1.443 +
   1.444 +bool elfGetObject(char *name, Function *f, CompileUnit *u, Object **o)
   1.445 +{
   1.446 +	if (f && u)
   1.447 +	{
   1.448 +		Object *v = f->variables;
   1.449 +
   1.450 +		while (v)
   1.451 +		{
   1.452 +			if (strcmp(name, v->name) == 0)
   1.453 +			{
   1.454 +				*o = v;
   1.455 +				return true;
   1.456 +			}
   1.457 +			v = v->next;
   1.458 +		}
   1.459 +		v = f->parameters;
   1.460 +		while (v)
   1.461 +		{
   1.462 +			if (strcmp(name, v->name) == 0)
   1.463 +			{
   1.464 +				*o = v;
   1.465 +				return true;
   1.466 +			}
   1.467 +			v = v->next;
   1.468 +		}
   1.469 +		v = u->variables;
   1.470 +		while (v)
   1.471 +		{
   1.472 +			if (strcmp(name, v->name) == 0)
   1.473 +			{
   1.474 +				*o = v;
   1.475 +				return true;
   1.476 +			}
   1.477 +			v = v->next;
   1.478 +		}
   1.479 +	}
   1.480 +
   1.481 +	CompileUnit *c = elfCompileUnits;
   1.482 +
   1.483 +	while (c)
   1.484 +	{
   1.485 +		if (c != u)
   1.486 +		{
   1.487 +			Object *v = c->variables;
   1.488 +			while (v)
   1.489 +			{
   1.490 +				if (strcmp(name, v->name) == 0)
   1.491 +				{
   1.492 +					*o = v;
   1.493 +					return true;
   1.494 +				}
   1.495 +				v = v->next;
   1.496 +			}
   1.497 +		}
   1.498 +		c = c->next;
   1.499 +	}
   1.500 +
   1.501 +	return false;
   1.502 +}
   1.503 +
   1.504 +char *elfGetSymbol(int i, u32 *value, u32 *size, int *type)
   1.505 +{
   1.506 +	if (i < elfSymbolsCount)
   1.507 +	{
   1.508 +		Symbol *s = &elfSymbols[i];
   1.509 +		*value = s->value;
   1.510 +		*size  = s->size;
   1.511 +		*type  = s->type;
   1.512 +		return s->name;
   1.513 +	}
   1.514 +	return NULL;
   1.515 +}
   1.516 +
   1.517 +bool elfGetSymbolAddress(char *sym, u32 *addr, u32 *size, int *type)
   1.518 +{
   1.519 +	if (elfSymbolsCount)
   1.520 +	{
   1.521 +		for (int i = 0; i < elfSymbolsCount; i++)
   1.522 +		{
   1.523 +			Symbol *s = &elfSymbols[i];
   1.524 +			if (strcmp(sym, s->name) == 0)
   1.525 +			{
   1.526 +				*addr = s->value;
   1.527 +				*size = s->size;
   1.528 +				*type = s->type;
   1.529 +				return true;
   1.530 +			}
   1.531 +		}
   1.532 +	}
   1.533 +	return false;
   1.534 +}
   1.535 +
   1.536 +ELFfde *elfGetFde(u32 address)
   1.537 +{
   1.538 +	if (elfFdes)
   1.539 +	{
   1.540 +		int i;
   1.541 +		for (i = 0; i < elfFdeCount; i++)
   1.542 +		{
   1.543 +			if (address >= elfFdes[i]->address &&
   1.544 +			    address < elfFdes[i]->end)
   1.545 +			{
   1.546 +				return elfFdes[i];
   1.547 +			}
   1.548 +		}
   1.549 +	}
   1.550 +
   1.551 +	return NULL;
   1.552 +}
   1.553 +
   1.554 +void elfExecuteCFAInstructions(ELFFrameState *state, u8 *data, u32 len,
   1.555 +                               u32 pc)
   1.556 +{
   1.557 +	u8 *end = data + len;
   1.558 +	int bytes;
   1.559 +	int reg;
   1.560 +	ELFFrameStateRegisters *fs;
   1.561 +
   1.562 +	while (data < end && state->pc < pc)
   1.563 +	{
   1.564 +		u8 op = *data++;
   1.565 +
   1.566 +		switch (op >> 6)
   1.567 +		{
   1.568 +		case DW_CFA_advance_loc:
   1.569 +			state->pc += (op & 0x3f) * state->codeAlign;
   1.570 +			break;
   1.571 +		case DW_CFA_offset:
   1.572 +			reg = op & 0x3f;
   1.573 +			state->registers.regs[reg].mode   = REG_OFFSET;
   1.574 +			state->registers.regs[reg].offset = state->dataAlign *
   1.575 +			                                    (s32)elfReadLEB128(data, &bytes);
   1.576 +			data += bytes;
   1.577 +			break;
   1.578 +		case DW_CFA_restore:
   1.579 +			// we don't care much about the other possible settings,
   1.580 +			// so just setting to unset is enough for now
   1.581 +			state->registers.regs[op & 0x3f].mode = REG_NOT_SET;
   1.582 +			break;
   1.583 +		case 0:
   1.584 +			switch (op & 0x3f)
   1.585 +			{
   1.586 +			case DW_CFA_nop:
   1.587 +				break;
   1.588 +			case DW_CFA_advance_loc1:
   1.589 +				state->pc += state->codeAlign * (*data++);
   1.590 +				break;
   1.591 +			case DW_CFA_advance_loc2:
   1.592 +				state->pc += state->codeAlign * elfRead2Bytes(data);
   1.593 +				data      += 2;
   1.594 +				break;
   1.595 +			case DW_CFA_advance_loc4:
   1.596 +				state->pc += state->codeAlign * elfRead4Bytes(data);
   1.597 +				data      += 4;
   1.598 +				break;
   1.599 +			case DW_CFA_offset_extended:
   1.600 +				reg   = elfReadLEB128(data, &bytes);
   1.601 +				data += bytes;
   1.602 +				state->registers.regs[reg].mode   = REG_OFFSET;
   1.603 +				state->registers.regs[reg].offset = state->dataAlign *
   1.604 +				                                    (s32)elfReadLEB128(data, &bytes);
   1.605 +				data += bytes;
   1.606 +				break;
   1.607 +			case DW_CFA_restore_extended:
   1.608 +			case DW_CFA_undefined:
   1.609 +			case DW_CFA_same_value:
   1.610 +				reg   = elfReadLEB128(data, &bytes);
   1.611 +				data += bytes;
   1.612 +				state->registers.regs[reg].mode = REG_NOT_SET;
   1.613 +				break;
   1.614 +			case DW_CFA_register:
   1.615 +				reg   = elfReadLEB128(data, &bytes);
   1.616 +				data += bytes;
   1.617 +				state->registers.regs[reg].mode = REG_REGISTER;
   1.618 +				state->registers.regs[reg].reg  = elfReadLEB128(data, &bytes);
   1.619 +				data += bytes;
   1.620 +				break;
   1.621 +			case DW_CFA_remember_state:
   1.622 +				fs = (ELFFrameStateRegisters *)calloc(1,
   1.623 +				                                      sizeof(ELFFrameStateRegisters));
   1.624 +				memcpy(fs, &state->registers, sizeof(ELFFrameStateRegisters));
   1.625 +				state->registers.previous = fs;
   1.626 +				break;
   1.627 +			case DW_CFA_restore_state:
   1.628 +				if (state->registers.previous == NULL)
   1.629 +				{
   1.630 +					printf("Error: previous frame state is NULL.\n");
   1.631 +					return;
   1.632 +				}
   1.633 +				fs = state->registers.previous;
   1.634 +				memcpy(&state->registers, fs, sizeof(ELFFrameStateRegisters));
   1.635 +				free(fs);
   1.636 +				break;
   1.637 +			case DW_CFA_def_cfa:
   1.638 +				state->cfaRegister = elfReadLEB128(data, &bytes);
   1.639 +				data += bytes;
   1.640 +				state->cfaOffset = (s32)elfReadLEB128(data, &bytes);
   1.641 +				data += bytes;
   1.642 +				state->cfaMode = CFA_REG_OFFSET;
   1.643 +				break;
   1.644 +			case DW_CFA_def_cfa_register:
   1.645 +				state->cfaRegister = elfReadLEB128(data, &bytes);
   1.646 +				data += bytes;
   1.647 +				state->cfaMode = CFA_REG_OFFSET;
   1.648 +				break;
   1.649 +			case DW_CFA_def_cfa_offset:
   1.650 +				state->cfaOffset = (s32)elfReadLEB128(data, &bytes);
   1.651 +				data += bytes;
   1.652 +				state->cfaMode = CFA_REG_OFFSET;
   1.653 +				break;
   1.654 +			default:
   1.655 +				printf("Unknown CFA opcode %08x\n", op);
   1.656 +				return;
   1.657 +			}
   1.658 +			break;
   1.659 +		default:
   1.660 +			printf("Unknown CFA opcode %08x\n", op);
   1.661 +			return;
   1.662 +		}
   1.663 +	}
   1.664 +}
   1.665 +
   1.666 +ELFFrameState *elfGetFrameState(ELFfde *fde, u32 address)
   1.667 +{
   1.668 +	ELFFrameState *state = (ELFFrameState *)calloc(1, sizeof(ELFFrameState));
   1.669 +	state->pc            = fde->address;
   1.670 +	state->dataAlign     = fde->cie->dataAlign;
   1.671 +	state->codeAlign     = fde->cie->codeAlign;
   1.672 +	state->returnAddress = fde->cie->returnAddress;
   1.673 +
   1.674 +	elfExecuteCFAInstructions(state,
   1.675 +	                          fde->cie->data,
   1.676 +	                          fde->cie->dataLen,
   1.677 +	                          0xffffffff);
   1.678 +	elfExecuteCFAInstructions(state,
   1.679 +	                          fde->data,
   1.680 +	                          fde->dataLen,
   1.681 +	                          address);
   1.682 +
   1.683 +	return state;
   1.684 +}
   1.685 +
   1.686 +void elfPrintCallChain(u32 address)
   1.687 +{
   1.688 +	int count = 1;
   1.689 +
   1.690 +	reg_pair regs[15];
   1.691 +	reg_pair newRegs[15];
   1.692 +
   1.693 +	memcpy(&regs[0], &reg[0], sizeof(reg_pair) * 15);
   1.694 +
   1.695 +	while (count < 20)
   1.696 +	{
   1.697 +		char *addr = elfGetAddressSymbol(address);
   1.698 +		if (*addr == 0)
   1.699 +			addr = "???";
   1.700 +
   1.701 +		printf("%08x %s\n", address, addr);
   1.702 +
   1.703 +		ELFfde *fde = elfGetFde(address);
   1.704 +
   1.705 +		if (fde == NULL)
   1.706 +		{
   1.707 +			break;
   1.708 +		}
   1.709 +
   1.710 +		ELFFrameState *state = elfGetFrameState(fde, address);
   1.711 +
   1.712 +		if (!state)
   1.713 +		{
   1.714 +			break;
   1.715 +		}
   1.716 +
   1.717 +		if (state->cfaMode == CFA_REG_OFFSET)
   1.718 +		{
   1.719 +			memcpy(&newRegs[0], &regs[0], sizeof(reg_pair) * 15);
   1.720 +			u32 addr = 0;
   1.721 +			for (int i = 0; i < 15; i++)
   1.722 +			{
   1.723 +				ELFFrameStateRegister *r = &state->registers.
   1.724 +				                           regs[i];
   1.725 +
   1.726 +				switch (r->mode)
   1.727 +				{
   1.728 +				case REG_NOT_SET:
   1.729 +					newRegs[i].I = regs[i].I;
   1.730 +					break;
   1.731 +				case REG_OFFSET:
   1.732 +					newRegs[i].I = elfReadMemory(regs[state->cfaRegister].I +
   1.733 +					                             state->cfaOffset +
   1.734 +					                             r->offset);
   1.735 +					break;
   1.736 +				case REG_REGISTER:
   1.737 +					newRegs[i].I = regs[r->reg].I;
   1.738 +					break;
   1.739 +				default:
   1.740 +					printf("Unknown register mode: %d\n", r->mode);
   1.741 +					break;
   1.742 +				}
   1.743 +			}
   1.744 +			memcpy(regs, newRegs, sizeof(reg_pair)*15);
   1.745 +			addr    = newRegs[14].I;
   1.746 +			addr   &= 0xfffffffe;
   1.747 +			address = addr;
   1.748 +			count++;
   1.749 +		}
   1.750 +		else
   1.751 +		{
   1.752 +			printf("CFA not set\n");
   1.753 +			break;
   1.754 +		}
   1.755 +		if (state->registers.previous)
   1.756 +		{
   1.757 +			ELFFrameStateRegisters *prev = state->registers.previous;
   1.758 +
   1.759 +			while (prev)
   1.760 +			{
   1.761 +				ELFFrameStateRegisters *p = prev->previous;
   1.762 +				free(prev);
   1.763 +				prev = p;
   1.764 +			}
   1.765 +		}
   1.766 +		free(state);
   1.767 +	}
   1.768 +}
   1.769 +
   1.770 +u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type, u32 base)
   1.771 +{
   1.772 +	u32 framebase = 0;
   1.773 +	if (f && f->frameBase)
   1.774 +	{
   1.775 +		ELFBlock *b = f->frameBase;
   1.776 +		switch (*b->data)
   1.777 +		{
   1.778 +		case DW_OP_reg0:
   1.779 +		case DW_OP_reg1:
   1.780 +		case DW_OP_reg2:
   1.781 +		case DW_OP_reg3:
   1.782 +		case DW_OP_reg4:
   1.783 +		case DW_OP_reg5:
   1.784 +		case DW_OP_reg6:
   1.785 +		case DW_OP_reg7:
   1.786 +		case DW_OP_reg8:
   1.787 +		case DW_OP_reg9:
   1.788 +		case DW_OP_reg10:
   1.789 +		case DW_OP_reg11:
   1.790 +		case DW_OP_reg12:
   1.791 +		case DW_OP_reg13:
   1.792 +		case DW_OP_reg14:
   1.793 +		case DW_OP_reg15:
   1.794 +			framebase = reg[*b->data-0x50].I;
   1.795 +			break;
   1.796 +		default:
   1.797 +			fprintf(stderr, "Unknown frameBase %02x\n", *b->data);
   1.798 +			break;
   1.799 +		}
   1.800 +	}
   1.801 +
   1.802 +	ELFBlock *loc      = o;
   1.803 +	u32       location = 0;
   1.804 +	int       bytes    = 0;
   1.805 +	if (loc)
   1.806 +	{
   1.807 +		switch (*loc->data)
   1.808 +		{
   1.809 +		case DW_OP_addr:
   1.810 +			location = elfRead4Bytes(loc->data+1);
   1.811 +			*type    = LOCATION_memory;
   1.812 +			break;
   1.813 +		case DW_OP_plus_uconst:
   1.814 +			location = base + elfReadLEB128(loc->data+1, &bytes);
   1.815 +			*type    = LOCATION_memory;
   1.816 +			break;
   1.817 +		case DW_OP_reg0:
   1.818 +		case DW_OP_reg1:
   1.819 +		case DW_OP_reg2:
   1.820 +		case DW_OP_reg3:
   1.821 +		case DW_OP_reg4:
   1.822 +		case DW_OP_reg5:
   1.823 +		case DW_OP_reg6:
   1.824 +		case DW_OP_reg7:
   1.825 +		case DW_OP_reg8:
   1.826 +		case DW_OP_reg9:
   1.827 +		case DW_OP_reg10:
   1.828 +		case DW_OP_reg11:
   1.829 +		case DW_OP_reg12:
   1.830 +		case DW_OP_reg13:
   1.831 +		case DW_OP_reg14:
   1.832 +		case DW_OP_reg15:
   1.833 +			location = *loc->data - 0x50;
   1.834 +			*type    = LOCATION_register;
   1.835 +			break;
   1.836 +		case DW_OP_fbreg:
   1.837 +		{
   1.838 +			int bytes;
   1.839 +			s32 off = elfReadSignedLEB128(loc->data+1, &bytes);
   1.840 +			location = framebase + off;
   1.841 +			*type    = LOCATION_memory;
   1.842 +			break;
   1.843 +		}
   1.844 +		default:
   1.845 +			fprintf(stderr, "Unknown location %02x\n", *loc->data);
   1.846 +			break;
   1.847 +		}
   1.848 +	}
   1.849 +	return location;
   1.850 +}
   1.851 +
   1.852 +u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type)
   1.853 +{
   1.854 +	return elfDecodeLocation(f, o, type, 0);
   1.855 +}
   1.856 +
   1.857 +// reading function
   1.858 +
   1.859 +u32 elfRead4Bytes(u8 *data)
   1.860 +{
   1.861 +	u32 value = *data++;
   1.862 +	value |= (*data++ << 8);
   1.863 +	value |= (*data++ << 16);
   1.864 +	value |= (*data << 24);
   1.865 +	return value;
   1.866 +}
   1.867 +
   1.868 +u16 elfRead2Bytes(u8 *data)
   1.869 +{
   1.870 +	u16 value = *data++;
   1.871 +	value |= (*data << 8);
   1.872 +	return value;
   1.873 +}
   1.874 +
   1.875 +char *elfReadString(u8 *data, int *bytesRead)
   1.876 +{
   1.877 +	if (*data == 0)
   1.878 +	{
   1.879 +		*bytesRead = 1;
   1.880 +		return NULL;
   1.881 +	}
   1.882 +	*bytesRead = strlen((char *)data) + 1;
   1.883 +	return (char *)data;
   1.884 +}
   1.885 +
   1.886 +s32 elfReadSignedLEB128(u8 *data, int *bytesRead)
   1.887 +{
   1.888 +	s32 result = 0;
   1.889 +	int shift  = 0;
   1.890 +	int count  = 0;
   1.891 +
   1.892 +	u8 byte;
   1.893 +	do
   1.894 +	{
   1.895 +		byte = *data++;
   1.896 +		count++;
   1.897 +		result |= (byte & 0x7f) << shift;
   1.898 +		shift  += 7;
   1.899 +	}
   1.900 +	while (byte & 0x80);
   1.901 +	if ((shift < 32) && (byte & 0x40))
   1.902 +		result |= -(1 << shift);
   1.903 +	*bytesRead = count;
   1.904 +	return result;
   1.905 +}
   1.906 +
   1.907 +u32 elfReadLEB128(u8 *data, int *bytesRead)
   1.908 +{
   1.909 +	u32 result = 0;
   1.910 +	int shift  = 0;
   1.911 +	int count  = 0;
   1.912 +	u8  byte;
   1.913 +	do
   1.914 +	{
   1.915 +		byte = *data++;
   1.916 +		count++;
   1.917 +		result |= (byte & 0x7f) << shift;
   1.918 +		shift  += 7;
   1.919 +	}
   1.920 +	while (byte & 0x80);
   1.921 +	*bytesRead = count;
   1.922 +	return result;
   1.923 +}
   1.924 +
   1.925 +u8 *elfReadSection(u8 *data, ELFSectionHeader *sh)
   1.926 +{
   1.927 +	return data + READ32LE(&sh->offset);
   1.928 +}
   1.929 +
   1.930 +ELFSectionHeader *elfGetSectionByName(char *name)
   1.931 +{
   1.932 +	for (int i = 0; i < elfSectionHeadersCount; i++)
   1.933 +	{
   1.934 +		if (strcmp(name,
   1.935 +		           &elfSectionHeadersStringTable[READ32LE(&elfSectionHeaders[i]->
   1.936 +		                                                  name)]) == 0)
   1.937 +		{
   1.938 +			return elfSectionHeaders[i];
   1.939 +		}
   1.940 +	}
   1.941 +	return NULL;
   1.942 +}
   1.943 +
   1.944 +ELFSectionHeader *elfGetSectionByNumber(int number)
   1.945 +{
   1.946 +	if (number < elfSectionHeadersCount)
   1.947 +	{
   1.948 +		return elfSectionHeaders[number];
   1.949 +	}
   1.950 +	return NULL;
   1.951 +}
   1.952 +
   1.953 +CompileUnit *elfGetCompileUnitForData(u8 *data)
   1.954 +{
   1.955 +	u8 *end = elfCurrentUnit->top + 4 + elfCurrentUnit->length;
   1.956 +
   1.957 +	if (data >= elfCurrentUnit->top && data < end)
   1.958 +		return elfCurrentUnit;
   1.959 +
   1.960 +	CompileUnit *unit = elfCompileUnits;
   1.961 +
   1.962 +	while (unit)
   1.963 +	{
   1.964 +		end = unit->top + 4 + unit->length;
   1.965 +
   1.966 +		if (data >= unit->top && data < end)
   1.967 +			return unit;
   1.968 +
   1.969 +		unit = unit->next;
   1.970 +	}
   1.971 +
   1.972 +	printf("Error: cannot find reference to compile unit at offset %08x\n",
   1.973 +	       (int)(data - elfDebugInfo->infodata));
   1.974 +	exit(-1);
   1.975 +}
   1.976 +
   1.977 +u8 *elfReadAttribute(u8 *data, ELFAttr *attr)
   1.978 +{
   1.979 +	int bytes;
   1.980 +	int form = attr->form;
   1.981 +start:
   1.982 +	switch (form)
   1.983 +	{
   1.984 +	case DW_FORM_addr:
   1.985 +		attr->value = elfRead4Bytes(data);
   1.986 +		data       += 4;
   1.987 +		break;
   1.988 +	case DW_FORM_data2:
   1.989 +		attr->value = elfRead2Bytes(data);
   1.990 +		data       += 2;
   1.991 +		break;
   1.992 +	case DW_FORM_data4:
   1.993 +		attr->value = elfRead4Bytes(data);
   1.994 +		data       += 4;
   1.995 +		break;
   1.996 +	case DW_FORM_string:
   1.997 +		attr->string = (char *)data;
   1.998 +		data        += strlen(attr->string)+1;
   1.999 +		break;
  1.1000 +	case DW_FORM_strp:
  1.1001 +		attr->string = elfDebugStrings + elfRead4Bytes(data);
  1.1002 +		data        += 4;
  1.1003 +		break;
  1.1004 +	case DW_FORM_block:
  1.1005 +		attr->block         = (ELFBlock *)malloc(sizeof(ELFBlock));
  1.1006 +		attr->block->length = elfReadLEB128(data, &bytes);
  1.1007 +		data += bytes;
  1.1008 +		attr->block->data = data;
  1.1009 +		data += attr->block->length;
  1.1010 +		break;
  1.1011 +	case DW_FORM_block1:
  1.1012 +		attr->block         = (ELFBlock *)malloc(sizeof(ELFBlock));
  1.1013 +		attr->block->length = *data++;
  1.1014 +		attr->block->data   = data;
  1.1015 +		data += attr->block->length;
  1.1016 +		break;
  1.1017 +	case DW_FORM_data1:
  1.1018 +		attr->value = *data++;
  1.1019 +		break;
  1.1020 +	case DW_FORM_flag:
  1.1021 +		attr->flag = (*data++) ? true : false;
  1.1022 +		break;
  1.1023 +	case DW_FORM_sdata:
  1.1024 +		attr->value = elfReadSignedLEB128(data, &bytes);
  1.1025 +		data       += bytes;
  1.1026 +		break;
  1.1027 +	case DW_FORM_udata:
  1.1028 +		attr->value = elfReadLEB128(data, &bytes);
  1.1029 +		data       += bytes;
  1.1030 +		break;
  1.1031 +	case DW_FORM_ref_addr:
  1.1032 +		attr->value = (elfDebugInfo->infodata + elfRead4Bytes(data)) -
  1.1033 +		              elfGetCompileUnitForData(data)->top;
  1.1034 +		data += 4;
  1.1035 +		break;
  1.1036 +	case DW_FORM_ref4:
  1.1037 +		attr->value = elfRead4Bytes(data);
  1.1038 +		data       += 4;
  1.1039 +		break;
  1.1040 +	case DW_FORM_ref_udata:
  1.1041 +		attr->value = (elfDebugInfo->infodata +
  1.1042 +		               (elfGetCompileUnitForData(data)->top -
  1.1043 +		                elfDebugInfo->infodata) +
  1.1044 +		               elfReadLEB128(data, &bytes)) -
  1.1045 +		              elfCurrentUnit->top;
  1.1046 +		data += bytes;
  1.1047 +		break;
  1.1048 +	case DW_FORM_indirect:
  1.1049 +		form  = elfReadLEB128(data, &bytes);
  1.1050 +		data += bytes;
  1.1051 +		goto start;
  1.1052 +	default:
  1.1053 +		fprintf(stderr, "Unsupported FORM %02x\n", form);
  1.1054 +		exit(-1);
  1.1055 +	}
  1.1056 +	return data;
  1.1057 +}
  1.1058 +
  1.1059 +ELFAbbrev *elfGetAbbrev(ELFAbbrev **table, u32 number)
  1.1060 +{
  1.1061 +	int hash = number % 121;
  1.1062 +
  1.1063 +	ELFAbbrev *abbrev = table[hash];
  1.1064 +
  1.1065 +	while (abbrev)
  1.1066 +	{
  1.1067 +		if (abbrev->number == number)
  1.1068 +			return abbrev;
  1.1069 +		abbrev = abbrev->next;
  1.1070 +	}
  1.1071 +	return NULL;
  1.1072 +}
  1.1073 +
  1.1074 +ELFAbbrev * *elfReadAbbrevs(u8 *data, u32 offset)
  1.1075 +{
  1.1076 +	data += offset;
  1.1077 +	ELFAbbrev **abbrevs = (ELFAbbrev * *)calloc(sizeof(ELFAbbrev *)*121, 1);
  1.1078 +	int         bytes   = 0;
  1.1079 +	u32         number  = elfReadLEB128(data, &bytes);
  1.1080 +	data += bytes;
  1.1081 +	while (number)
  1.1082 +	{
  1.1083 +		ELFAbbrev *abbrev = (ELFAbbrev *)calloc(sizeof(ELFAbbrev), 1);
  1.1084 +
  1.1085 +		// read tag information
  1.1086 +		abbrev->number = number;
  1.1087 +		abbrev->tag    = elfReadLEB128(data, &bytes);
  1.1088 +		data += bytes;
  1.1089 +		abbrev->hasChildren = *data++ ? true : false;
  1.1090 +
  1.1091 +		// read attributes
  1.1092 +		int name = elfReadLEB128(data, &bytes);
  1.1093 +		data += bytes;
  1.1094 +		int form = elfReadLEB128(data, &bytes);
  1.1095 +		data += bytes;
  1.1096 +
  1.1097 +		while (name)
  1.1098 +		{
  1.1099 +			if ((abbrev->numAttrs % 4) == 0)
  1.1100 +			{
  1.1101 +				abbrev->attrs = (ELFAttr *)realloc(abbrev->attrs,
  1.1102 +				                                   (abbrev->numAttrs + 4) *
  1.1103 +				                                   sizeof(ELFAttr));
  1.1104 +			}
  1.1105 +			abbrev->attrs[abbrev->numAttrs].name   = name;
  1.1106 +			abbrev->attrs[abbrev->numAttrs++].form = form;
  1.1107 +
  1.1108 +			name  = elfReadLEB128(data, &bytes);
  1.1109 +			data += bytes;
  1.1110 +			form  = elfReadLEB128(data, &bytes);
  1.1111 +			data += bytes;
  1.1112 +		}
  1.1113 +
  1.1114 +		int hash = number % 121;
  1.1115 +		abbrev->next  = abbrevs[hash];
  1.1116 +		abbrevs[hash] = abbrev;
  1.1117 +
  1.1118 +		number = elfReadLEB128(data, &bytes);
  1.1119 +		data  += bytes;
  1.1120 +
  1.1121 +		if (elfGetAbbrev(abbrevs, number) != NULL)
  1.1122 +			break;
  1.1123 +	}
  1.1124 +
  1.1125 +	return abbrevs;
  1.1126 +}
  1.1127 +
  1.1128 +void elfParseCFA(u8 *top)
  1.1129 +{
  1.1130 +	ELFSectionHeader *h = elfGetSectionByName(".debug_frame");
  1.1131 +
  1.1132 +	if (h == NULL)
  1.1133 +	{
  1.1134 +		return;
  1.1135 +	}
  1.1136 +
  1.1137 +	u8 *data = elfReadSection(top, h);
  1.1138 +
  1.1139 +	u8 *topOffset = data;
  1.1140 +
  1.1141 +	u8 *end = data + READ32LE(&h->size);
  1.1142 +
  1.1143 +	ELFcie *cies = NULL;
  1.1144 +
  1.1145 +	while (data < end)
  1.1146 +	{
  1.1147 +		u32 offset = data - topOffset;
  1.1148 +		u32 len    = elfRead4Bytes(data);
  1.1149 +		data += 4;
  1.1150 +
  1.1151 +		u8 *dataEnd = data + len;
  1.1152 +
  1.1153 +		u32 id = elfRead4Bytes(data);
  1.1154 +		data += 4;
  1.1155 +
  1.1156 +		if (id == 0xffffffff)
  1.1157 +		{
  1.1158 +			// skip version
  1.1159 +			*data++;
  1.1160 +
  1.1161 +			ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie));
  1.1162 +
  1.1163 +			cie->next = cies;
  1.1164 +			cies      = cie;
  1.1165 +
  1.1166 +			cie->offset = offset;
  1.1167 +
  1.1168 +			cie->augmentation = data;
  1.1169 +			while (*data)
  1.1170 +				data++;
  1.1171 +			data++;
  1.1172 +
  1.1173 +			if (*cie->augmentation)
  1.1174 +			{
  1.1175 +				fprintf(stderr, "Error: augmentation not supported\n");
  1.1176 +				exit(-1);
  1.1177 +			}
  1.1178 +
  1.1179 +			int bytes;
  1.1180 +			cie->codeAlign = elfReadLEB128(data, &bytes);
  1.1181 +			data += bytes;
  1.1182 +
  1.1183 +			cie->dataAlign = elfReadSignedLEB128(data, &bytes);
  1.1184 +			data += bytes;
  1.1185 +
  1.1186 +			cie->returnAddress = *data++;
  1.1187 +
  1.1188 +			cie->data    = data;
  1.1189 +			cie->dataLen = dataEnd - data;
  1.1190 +		}
  1.1191 +		else
  1.1192 +		{
  1.1193 +			ELFfde *fde = (ELFfde *)calloc(1, sizeof(ELFfde));
  1.1194 +
  1.1195 +			ELFcie *cie = cies;
  1.1196 +
  1.1197 +			while (cie != NULL)
  1.1198 +			{
  1.1199 +				if (cie->offset == id)
  1.1200 +					break;
  1.1201 +				cie = cie->next;
  1.1202 +			}
  1.1203 +
  1.1204 +			if (!cie)
  1.1205 +			{
  1.1206 +				fprintf(stderr, "Cannot find CIE %08x\n", id);
  1.1207 +				exit(-1);
  1.1208 +			}
  1.1209 +
  1.1210 +			fde->cie = cie;
  1.1211 +
  1.1212 +			fde->address = elfRead4Bytes(data);
  1.1213 +			data        += 4;
  1.1214 +
  1.1215 +			fde->end = fde->address + elfRead4Bytes(data);
  1.1216 +			data    += 4;
  1.1217 +
  1.1218 +			fde->data    = data;
  1.1219 +			fde->dataLen = dataEnd - data;
  1.1220 +
  1.1221 +			if ((elfFdeCount %10) == 0)
  1.1222 +			{
  1.1223 +				elfFdes = (ELFfde * *)realloc(elfFdes, (elfFdeCount+10) *
  1.1224 +				                              sizeof(ELFfde *));
  1.1225 +			}
  1.1226 +			elfFdes[elfFdeCount++] = fde;
  1.1227 +		}
  1.1228 +		data = dataEnd;
  1.1229 +	}
  1.1230 +
  1.1231 +	elfCies = cies;
  1.1232 +}
  1.1233 +
  1.1234 +void elfAddLine(LineInfo *l, u32 a, int file, int line, int *max)
  1.1235 +{
  1.1236 +	if (l->number == *max)
  1.1237 +	{
  1.1238 +		*max    += 1000;
  1.1239 +		l->lines = (LineInfoItem *)realloc(l->lines, *max*sizeof(LineInfoItem));
  1.1240 +	}
  1.1241 +	LineInfoItem *li = &l->lines[l->number];
  1.1242 +	li->file    = l->files[file-1];
  1.1243 +	li->address = a;
  1.1244 +	li->line    = line;
  1.1245 +	l->number++;
  1.1246 +}
  1.1247 +
  1.1248 +void elfParseLineInfo(CompileUnit *unit, u8 *top)
  1.1249 +{
  1.1250 +	ELFSectionHeader *h = elfGetSectionByName(".debug_line");
  1.1251 +	if (h == NULL)
  1.1252 +	{
  1.1253 +		fprintf(stderr, "No line information found\n");
  1.1254 +		return;
  1.1255 +	}
  1.1256 +	LineInfo *l = unit->lineInfoTable = (LineInfo *)calloc(1, sizeof(LineInfo));
  1.1257 +	l->number = 0;
  1.1258 +	int max = 1000;
  1.1259 +	l->lines = (LineInfoItem *)malloc(1000*sizeof(LineInfoItem));
  1.1260 +
  1.1261 +	u8 *data = elfReadSection(top, h);
  1.1262 +	data += unit->lineInfo;
  1.1263 +	u32 totalLen = elfRead4Bytes(data);
  1.1264 +	data += 4;
  1.1265 +	u8 *end = data + totalLen;
  1.1266 +	//  u16 version = elfRead2Bytes(data);
  1.1267 +	data += 2;
  1.1268 +	//  u32 offset = elfRead4Bytes(data);
  1.1269 +	data += 4;
  1.1270 +	int minInstrSize  = *data++;
  1.1271 +	int defaultIsStmt = *data++;
  1.1272 +	int lineBase      = (s8)*data++;
  1.1273 +	int lineRange     = *data++;
  1.1274 +	int opcodeBase    = *data++;
  1.1275 +	u8 *stdOpLen      = (u8 *)malloc(opcodeBase * sizeof(u8));
  1.1276 +	stdOpLen[0] = 1;
  1.1277 +	int i;
  1.1278 +	for (i = 1; i < opcodeBase; i++)
  1.1279 +		stdOpLen[i] = *data++;
  1.1280 +
  1.1281 +	free(stdOpLen); // todo
  1.1282 +	int bytes = 0;
  1.1283 +
  1.1284 +	char *s;
  1.1285 +	while ((s = elfReadString(data, &bytes)) != NULL)
  1.1286 +	{
  1.1287 +		data += bytes;
  1.1288 +		//    fprintf(stderr, "Directory is %s\n", s);
  1.1289 +	}
  1.1290 +	data += bytes;
  1.1291 +	int count = 4;
  1.1292 +	int index = 0;
  1.1293 +	l->files = (char * *)malloc(sizeof(char *)*count);
  1.1294 +
  1.1295 +	while ((s = elfReadString(data, &bytes)) != NULL)
  1.1296 +	{
  1.1297 +		l->files[index++] = s;
  1.1298 +
  1.1299 +		data += bytes;
  1.1300 +		// directory
  1.1301 +		elfReadLEB128(data, &bytes);
  1.1302 +		data += bytes;
  1.1303 +		// time
  1.1304 +		elfReadLEB128(data, &bytes);
  1.1305 +		data += bytes;
  1.1306 +		// size
  1.1307 +		elfReadLEB128(data, &bytes);
  1.1308 +		data += bytes;
  1.1309 +		//    fprintf(stderr, "File is %s\n", s);
  1.1310 +		if (index == count)
  1.1311 +		{
  1.1312 +			count   += 4;
  1.1313 +			l->files = (char * *)realloc(l->files, sizeof(char *)*count);
  1.1314 +		}
  1.1315 +	}
  1.1316 +	l->fileCount = index;
  1.1317 +	data        += bytes;
  1.1318 +
  1.1319 +	while (data < end)
  1.1320 +	{
  1.1321 +		u32 address    = 0;
  1.1322 +		int file       = 1;
  1.1323 +		int line       = 1;
  1.1324 +		int col        = 0;
  1.1325 +		int isStmt     = defaultIsStmt;
  1.1326 +		int basicBlock = 0;
  1.1327 +		int endSeq     = 0;
  1.1328 +
  1.1329 +		while (!endSeq)
  1.1330 +		{
  1.1331 +			int op = *data++;
  1.1332 +			switch (op)
  1.1333 +			{
  1.1334 +			case DW_LNS_extended_op:
  1.1335 +			{
  1.1336 +				data++;
  1.1337 +				op = *data++;
  1.1338 +				switch (op)
  1.1339 +				{
  1.1340 +				case DW_LNE_end_sequence:
  1.1341 +					endSeq = 1;
  1.1342 +					break;
  1.1343 +				case DW_LNE_set_address:
  1.1344 +					address = elfRead4Bytes(data);
  1.1345 +					data   += 4;
  1.1346 +					break;
  1.1347 +				default:
  1.1348 +					fprintf(stderr, "Unknown extended LINE opcode %02x\n", op);
  1.1349 +					exit(-1);
  1.1350 +				}
  1.1351 +				break;
  1.1352 +			}
  1.1353 +			case DW_LNS_copy:
  1.1354 +				//      fprintf(stderr, "Address %08x line %d (%d)\n", address, line, file);
  1.1355 +				elfAddLine(l, address, file, line, &max);
  1.1356 +				basicBlock = 0;
  1.1357 +				break;
  1.1358 +			case DW_LNS_advance_pc:
  1.1359 +				address += minInstrSize * elfReadLEB128(data, &bytes);
  1.1360 +				data    += bytes;
  1.1361 +				break;
  1.1362 +			case DW_LNS_advance_line:
  1.1363 +				line += elfReadSignedLEB128(data, &bytes);
  1.1364 +				data += bytes;
  1.1365 +				break;
  1.1366 +			case DW_LNS_set_file:
  1.1367 +				file  = elfReadLEB128(data, &bytes);
  1.1368 +				data += bytes;
  1.1369 +				break;
  1.1370 +			case DW_LNS_set_column:
  1.1371 +				col   = elfReadLEB128(data, &bytes);
  1.1372 +				data += bytes;
  1.1373 +				break;
  1.1374 +			case DW_LNS_negate_stmt:
  1.1375 +				isStmt = !isStmt;
  1.1376 +				break;
  1.1377 +			case DW_LNS_set_basic_block:
  1.1378 +				basicBlock = 1;
  1.1379 +				break;
  1.1380 +			case DW_LNS_const_add_pc:
  1.1381 +				address += (minInstrSize *((255 - opcodeBase)/lineRange));
  1.1382 +				break;
  1.1383 +			case DW_LNS_fixed_advance_pc:
  1.1384 +				address += elfRead2Bytes(data);
  1.1385 +				data    += 2;
  1.1386 +				break;
  1.1387 +			default:
  1.1388 +				op       = op - opcodeBase;
  1.1389 +				address += (op / lineRange) * minInstrSize;
  1.1390 +				line    += lineBase + (op % lineRange);
  1.1391 +				elfAddLine(l, address, file, line, &max);
  1.1392 +				//        fprintf(stderr, "Address %08x line %d (%d)\n", address, line,file);
  1.1393 +				basicBlock = 1;
  1.1394 +				break;
  1.1395 +			}
  1.1396 +		}
  1.1397 +	}
  1.1398 +	l->lines = (LineInfoItem *)realloc(l->lines, l->number*sizeof(LineInfoItem));
  1.1399 +}
  1.1400 +
  1.1401 +u8 *elfSkipData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs)
  1.1402 +{
  1.1403 +	int i;
  1.1404 +	int bytes;
  1.1405 +
  1.1406 +	for (i = 0; i < abbrev->numAttrs; i++)
  1.1407 +	{
  1.1408 +		data = elfReadAttribute(data,  &abbrev->attrs[i]);
  1.1409 +		if (abbrev->attrs[i].form == DW_FORM_block1)
  1.1410 +			free(abbrev->attrs[i].block);
  1.1411 +	}
  1.1412 +
  1.1413 +	if (abbrev->hasChildren)
  1.1414 +	{
  1.1415 +		int nesting = 1;
  1.1416 +		while (nesting)
  1.1417 +		{
  1.1418 +			u32 abbrevNum = elfReadLEB128(data, &bytes);
  1.1419 +			data += bytes;
  1.1420 +
  1.1421 +			if (!abbrevNum)
  1.1422 +			{
  1.1423 +				nesting--;
  1.1424 +				continue;
  1.1425 +			}
  1.1426 +
  1.1427 +			abbrev = elfGetAbbrev(abbrevs, abbrevNum);
  1.1428 +
  1.1429 +			for (i = 0; i < abbrev->numAttrs; i++)
  1.1430 +			{
  1.1431 +				data = elfReadAttribute(data,  &abbrev->attrs[i]);
  1.1432 +				if (abbrev->attrs[i].form == DW_FORM_block1)
  1.1433 +					free(abbrev->attrs[i].block);
  1.1434 +			}
  1.1435 +
  1.1436 +			if (abbrev->hasChildren)
  1.1437 +			{
  1.1438 +				nesting++;
  1.1439 +			}
  1.1440 +		}
  1.1441 +	}
  1.1442 +	return data;
  1.1443 +}
  1.1444 +
  1.1445 +Type *elfParseType(CompileUnit *unit, u32);
  1.1446 +u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
  1.1447 +                   Object **object);
  1.1448 +u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
  1.1449 +                     Function **function);
  1.1450 +void elfCleanUp(Function *);
  1.1451 +
  1.1452 +void elfAddType(Type *type, CompileUnit *unit, u32 offset)
  1.1453 +{
  1.1454 +	if (type->next == NULL)
  1.1455 +	{
  1.1456 +		if (unit->types != type && type->offset == 0)
  1.1457 +		{
  1.1458 +			type->offset = offset;
  1.1459 +			type->next   = unit->types;
  1.1460 +			unit->types  = type;
  1.1461 +		}
  1.1462 +	}
  1.1463 +}
  1.1464 +
  1.1465 +void elfParseType(u8 *data, u32 offset, ELFAbbrev *abbrev, CompileUnit *unit,
  1.1466 +                  Type **type)
  1.1467 +{
  1.1468 +	switch (abbrev->tag)
  1.1469 +	{
  1.1470 +	case DW_TAG_typedef:
  1.1471 +	{
  1.1472 +		u32   typeref = 0;
  1.1473 +		char *name    = NULL;
  1.1474 +		for (int i = 0; i < abbrev->numAttrs; i++)
  1.1475 +		{
  1.1476 +			ELFAttr *attr = &abbrev->attrs[i];
  1.1477 +			data = elfReadAttribute(data, attr);
  1.1478 +			switch (attr->name)
  1.1479 +			{
  1.1480 +			case DW_AT_name:
  1.1481 +				name = attr->string;
  1.1482 +				break;
  1.1483 +			case DW_AT_type:
  1.1484 +				typeref = attr->value;
  1.1485 +				break;
  1.1486 +			case DW_AT_decl_file:
  1.1487 +			case DW_AT_decl_line:
  1.1488 +				break;
  1.1489 +			default:
  1.1490 +				fprintf(stderr, "Unknown attribute for typedef %02x\n", attr->name);
  1.1491 +				break;
  1.1492 +			}
  1.1493 +		}
  1.1494 +		if (abbrev->hasChildren)
  1.1495 +			fprintf(stderr, "Unexpected children for typedef\n");
  1.1496 +		*type = elfParseType(unit, typeref);
  1.1497 +		if (name)
  1.1498 +			(*type)->name = name;
  1.1499 +		return;
  1.1500 +		break;
  1.1501 +	}
  1.1502 +	case DW_TAG_union_type:
  1.1503 +	case DW_TAG_structure_type:
  1.1504 +	{
  1.1505 +		Type *t = (Type *)calloc(sizeof(Type), 1);
  1.1506 +		if (abbrev->tag == DW_TAG_structure_type)
  1.1507 +			t->type = TYPE_struct;
  1.1508 +		else
  1.1509 +			t->type = TYPE_union;
  1.1510 +
  1.1511 +		Struct *s = (Struct *)calloc(sizeof(Struct), 1);
  1.1512 +		t->structure = s;
  1.1513 +		elfAddType(t, unit, offset);
  1.1514 +
  1.1515 +		for (int i = 0; i < abbrev->numAttrs; i++)
  1.1516 +		{
  1.1517 +			ELFAttr *attr = &abbrev->attrs[i];
  1.1518 +			data = elfReadAttribute(data, attr);
  1.1519 +			switch (attr->name)
  1.1520 +			{
  1.1521 +			case DW_AT_name:
  1.1522 +				t->name = attr->string;
  1.1523 +				break;
  1.1524 +			case DW_AT_byte_size:
  1.1525 +				t->size = attr->value;
  1.1526 +				break;
  1.1527 +			case DW_AT_decl_file:
  1.1528 +			case DW_AT_decl_line:
  1.1529 +			case DW_AT_sibling:
  1.1530 +			case DW_AT_containing_type: // todo?
  1.1531 +			case DW_AT_declaration:
  1.1532 +			case DW_AT_specification: // TODO:
  1.1533 +				break;
  1.1534 +			default:
  1.1535 +				fprintf(stderr, "Unknown attribute for struct %02x\n", attr->name);
  1.1536 +				break;
  1.1537 +			}
  1.1538 +		}
  1.1539 +		if (abbrev->hasChildren)
  1.1540 +		{
  1.1541 +			int bytes;
  1.1542 +			u32 num = elfReadLEB128(data, &bytes);
  1.1543 +			data += bytes;
  1.1544 +			int index = 0;
  1.1545 +			while (num)
  1.1546 +			{
  1.1547 +				ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
  1.1548 +
  1.1549 +				switch (abbr->tag)
  1.1550 +				{
  1.1551 +				case DW_TAG_member:
  1.1552 +				{
  1.1553 +					if ((index % 4) == 0)
  1.1554 +						s->members = (Member *)realloc(s->members,
  1.1555 +						                               sizeof(Member)*(index+4));
  1.1556 +					Member *m = &s->members[index];
  1.1557 +					m->location  = NULL;
  1.1558 +					m->bitOffset = 0;
  1.1559 +					m->bitSize   = 0;
  1.1560 +					m->byteSize  = 0;
  1.1561 +					for (int i = 0; i < abbr->numAttrs; i++)
  1.1562 +					{
  1.1563 +						ELFAttr *attr = &abbr->attrs[i];
  1.1564 +						data = elfReadAttribute(data, attr);
  1.1565 +						switch (attr->name)
  1.1566 +						{
  1.1567 +						case DW_AT_name:
  1.1568 +							m->name = attr->string;
  1.1569 +							break;
  1.1570 +						case DW_AT_type:
  1.1571 +							m->type = elfParseType(unit, attr->value);
  1.1572 +							break;
  1.1573 +						case DW_AT_data_member_location:
  1.1574 +							m->location = attr->block;
  1.1575 +							break;
  1.1576 +						case DW_AT_byte_size:
  1.1577 +							m->byteSize = attr->value;
  1.1578 +							break;
  1.1579 +						case DW_AT_bit_offset:
  1.1580 +							m->bitOffset = attr->value;
  1.1581 +							break;
  1.1582 +						case DW_AT_bit_size:
  1.1583 +							m->bitSize = attr->value;
  1.1584 +							break;
  1.1585 +						case DW_AT_decl_file:
  1.1586 +						case DW_AT_decl_line:
  1.1587 +						case DW_AT_accessibility:
  1.1588 +						case DW_AT_artificial: // todo?
  1.1589 +							break;
  1.1590 +						default:
  1.1591 +							fprintf(stderr, "Unknown member attribute %02x\n",
  1.1592 +							        attr->name);
  1.1593 +						}
  1.1594 +					}
  1.1595 +					index++;
  1.1596 +					break;
  1.1597 +				}
  1.1598 +				case DW_TAG_subprogram:
  1.1599 +				{
  1.1600 +					Function *fnc = NULL;
  1.1601 +					data = elfParseFunction(data, abbr, unit, &fnc);
  1.1602 +					if (fnc != NULL)
  1.1603 +					{
  1.1604 +						if (unit->lastFunction)
  1.1605 +							unit->lastFunction->next = fnc;
  1.1606 +						else
  1.1607 +							unit->functions = fnc;
  1.1608 +						unit->lastFunction = fnc;
  1.1609 +					}
  1.1610 +					break;
  1.1611 +				}
  1.1612 +				case DW_TAG_inheritance:
  1.1613 +					// TODO: add support
  1.1614 +					data = elfSkipData(data, abbr, unit->abbrevs);
  1.1615 +					break;
  1.1616 +CASE_TYPE_TAG:
  1.1617 +					// skip types... parsed only when used
  1.1618 +					data = elfSkipData(data, abbr, unit->abbrevs);
  1.1619 +					break;
  1.1620 +				case DW_TAG_variable:
  1.1621 +					data = elfSkipData(data, abbr, unit->abbrevs);
  1.1622 +					break;
  1.1623 +				default:
  1.1624 +					fprintf(stderr, "Unknown struct tag %02x %s\n", abbr->tag, t->name);
  1.1625 +					data = elfSkipData(data, abbr, unit->abbrevs);
  1.1626 +					break;
  1.1627 +				}
  1.1628 +				num   = elfReadLEB128(data, &bytes);
  1.1629 +				data += bytes;
  1.1630 +			}
  1.1631 +			s->memberCount = index;
  1.1632 +		}
  1.1633 +		*type = t;
  1.1634 +		return;
  1.1635 +		break;
  1.1636 +	}
  1.1637 +	case DW_TAG_base_type:
  1.1638 +	{
  1.1639 +		Type *t = (Type *)calloc(sizeof(Type), 1);
  1.1640 +
  1.1641 +		t->type = TYPE_base;
  1.1642 +		elfAddType(t, unit, offset);
  1.1643 +		for (int i = 0; i < abbrev->numAttrs; i++)
  1.1644 +		{
  1.1645 +			ELFAttr *attr = &abbrev->attrs[i];
  1.1646 +			data = elfReadAttribute(data, attr);
  1.1647 +			switch (attr->name)
  1.1648 +			{
  1.1649 +			case DW_AT_name:
  1.1650 +				t->name = attr->string;
  1.1651 +				break;
  1.1652 +			case DW_AT_encoding:
  1.1653 +				t->encoding = attr->value;
  1.1654 +				break;
  1.1655 +			case DW_AT_byte_size:
  1.1656 +				t->size = attr->value;
  1.1657 +				break;
  1.1658 +			case DW_AT_bit_size:
  1.1659 +				t->bitSize = attr->value;
  1.1660 +				break;
  1.1661 +			default:
  1.1662 +				fprintf(stderr, "Unknown attribute for base type %02x\n",
  1.1663 +				        attr->name);
  1.1664 +				break;
  1.1665 +			}
  1.1666 +		}
  1.1667 +		if (abbrev->hasChildren)
  1.1668 +			fprintf(stderr, "Unexpected children for base type\n");
  1.1669 +		*type = t;
  1.1670 +		return;
  1.1671 +		break;
  1.1672 +	}
  1.1673 +	case DW_TAG_pointer_type:
  1.1674 +	{
  1.1675 +		Type *t = (Type *)calloc(sizeof(Type), 1);
  1.1676 +
  1.1677 +		t->type = TYPE_pointer;
  1.1678 +
  1.1679 +		elfAddType(t, unit, offset);
  1.1680 +
  1.1681 +		for (int i = 0; i < abbrev->numAttrs; i++)
  1.1682 +		{
  1.1683 +			ELFAttr *attr = &abbrev->attrs[i];
  1.1684 +			data = elfReadAttribute(data, attr);
  1.1685 +			switch (attr->name)
  1.1686 +			{
  1.1687 +			case DW_AT_type:
  1.1688 +				t->pointer = elfParseType(unit, attr->value);
  1.1689 +				break;
  1.1690 +			case DW_AT_byte_size:
  1.1691 +				t->size = attr->value;
  1.1692 +				break;
  1.1693 +			default:
  1.1694 +				fprintf(stderr, "Unknown pointer type attribute %02x\n", attr->name);
  1.1695 +				break;
  1.1696 +			}
  1.1697 +		}
  1.1698 +		if (abbrev->hasChildren)
  1.1699 +			fprintf(stderr, "Unexpected children for pointer type\n");
  1.1700 +		*type = t;
  1.1701 +		return;
  1.1702 +		break;
  1.1703 +	}
  1.1704 +	case DW_TAG_reference_type:
  1.1705 +	{
  1.1706 +		Type *t = (Type *)calloc(sizeof(Type), 1);
  1.1707 +
  1.1708 +		t->type = TYPE_reference;
  1.1709 +
  1.1710 +		elfAddType(t, unit, offset);
  1.1711 +
  1.1712 +		for (int i = 0; i < abbrev->numAttrs; i++)
  1.1713 +		{
  1.1714 +			ELFAttr *attr = &abbrev->attrs[i];
  1.1715 +			data = elfReadAttribute(data, attr);
  1.1716 +			switch (attr->name)
  1.1717 +			{
  1.1718 +			case DW_AT_type:
  1.1719 +				t->pointer = elfParseType(unit, attr->value);
  1.1720 +				break;
  1.1721 +			case DW_AT_byte_size:
  1.1722 +				t->size = attr->value;
  1.1723 +				break;
  1.1724 +			default:
  1.1725 +				fprintf(stderr, "Unknown ref type attribute %02x\n", attr->name);
  1.1726 +				break;
  1.1727 +			}
  1.1728 +		}
  1.1729 +		if (abbrev->hasChildren)
  1.1730 +			fprintf(stderr, "Unexpected children for ref type\n");
  1.1731 +		*type = t;
  1.1732 +		return;
  1.1733 +		break;
  1.1734 +	}
  1.1735 +	case DW_TAG_volatile_type:
  1.1736 +	{
  1.1737 +		u32 typeref = 0;
  1.1738 +
  1.1739 +		for (int i = 0; i < abbrev->numAttrs; i++)
  1.1740 +		{
  1.1741 +			ELFAttr *attr = &abbrev->attrs[i];
  1.1742 +			data = elfReadAttribute(data, attr);
  1.1743 +			switch (attr->name)
  1.1744 +			{
  1.1745 +			case DW_AT_type:
  1.1746 +				typeref = attr->value;
  1.1747 +				break;
  1.1748 +			default:
  1.1749 +				fprintf(stderr, "Unknown volatile attribute for type %02x\n",
  1.1750 +				        attr->name);
  1.1751 +				break;
  1.1752 +			}
  1.1753 +		}
  1.1754 +		if (abbrev->hasChildren)
  1.1755 +			fprintf(stderr, "Unexpected children for volatile type\n");
  1.1756 +		*type = elfParseType(unit, typeref);
  1.1757 +		return;
  1.1758 +		break;
  1.1759 +	}
  1.1760 +	case DW_TAG_const_type:
  1.1761 +	{
  1.1762 +		u32 typeref = 0;
  1.1763 +
  1.1764 +		for (int i = 0; i < abbrev->numAttrs; i++)
  1.1765 +		{
  1.1766 +			ELFAttr *attr = &abbrev->attrs[i];
  1.1767 +			data = elfReadAttribute(data, attr);
  1.1768 +			switch (attr->name)
  1.1769 +			{
  1.1770 +			case DW_AT_type:
  1.1771 +				typeref = attr->value;
  1.1772 +				break;
  1.1773 +			default:
  1.1774 +				fprintf(stderr, "Unknown const attribute for type %02x\n",
  1.1775 +				        attr->name);
  1.1776 +				break;
  1.1777 +			}
  1.1778 +		}
  1.1779 +		if (abbrev->hasChildren)
  1.1780 +			fprintf(stderr, "Unexpected children for const type\n");
  1.1781 +		*type = elfParseType(unit, typeref);
  1.1782 +		return;
  1.1783 +		break;
  1.1784 +	}
  1.1785 +	case DW_TAG_enumeration_type:
  1.1786 +	{
  1.1787 +		Type *t = (Type *)calloc(sizeof(Type), 1);
  1.1788 +		t->type = TYPE_enum;
  1.1789 +		Enum *e = (Enum *)calloc(sizeof(Enum), 1);
  1.1790 +		t->enumeration = e;
  1.1791 +		elfAddType(t, unit, offset);
  1.1792 +		int count = 0;
  1.1793 +		for (int i = 0; i < abbrev->numAttrs; i++)
  1.1794 +		{
  1.1795 +			ELFAttr *attr = &abbrev->attrs[i];
  1.1796 +			data = elfReadAttribute(data, attr);
  1.1797 +			switch (attr->name)
  1.1798 +			{
  1.1799 +			case DW_AT_name:
  1.1800 +				t->name = attr->string;
  1.1801 +				break;
  1.1802 +			case DW_AT_byte_size:
  1.1803 +				t->size = attr->value;
  1.1804 +				break;
  1.1805 +			case DW_AT_sibling:
  1.1806 +			case DW_AT_decl_file:
  1.1807 +			case DW_AT_decl_line:
  1.1808 +				break;
  1.1809 +			default:
  1.1810 +				fprintf(stderr, "Unknown enum attribute %02x\n", attr->name);
  1.1811 +			}
  1.1812 +		}
  1.1813 +		if (abbrev->hasChildren)
  1.1814 +		{
  1.1815 +			int bytes;
  1.1816 +			u32 num = elfReadLEB128(data, &bytes);
  1.1817 +			data += bytes;
  1.1818 +			while (num)
  1.1819 +			{
  1.1820 +				ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
  1.1821 +
  1.1822 +				switch (abbr->tag)
  1.1823 +				{
  1.1824 +				case DW_TAG_enumerator:
  1.1825 +				{
  1.1826 +					count++;
  1.1827 +					e->members = (EnumMember *)realloc(e->members,
  1.1828 +					                                   count*sizeof(EnumMember));
  1.1829 +					EnumMember *m = &e->members[count-1];
  1.1830 +					for (int i = 0; i < abbr->numAttrs; i++)
  1.1831 +					{
  1.1832 +						ELFAttr *attr = &abbr->attrs[i];
  1.1833 +						data = elfReadAttribute(data, attr);
  1.1834 +						switch (attr->name)
  1.1835 +						{
  1.1836 +						case DW_AT_name:
  1.1837 +							m->name = attr->string;
  1.1838 +							break;
  1.1839 +						case DW_AT_const_value:
  1.1840 +							m->value = attr->value;
  1.1841 +							break;
  1.1842 +						default:
  1.1843 +							fprintf(stderr, "Unknown sub param attribute %02x\n",
  1.1844 +							        attr->name);
  1.1845 +						}
  1.1846 +					}
  1.1847 +					break;
  1.1848 +				}
  1.1849 +				default:
  1.1850 +					fprintf(stderr, "Unknown enum tag %02x\n", abbr->tag);
  1.1851 +					data = elfSkipData(data, abbr, unit->abbrevs);
  1.1852 +					break;
  1.1853 +				}
  1.1854 +				num   = elfReadLEB128(data, &bytes);
  1.1855 +				data += bytes;
  1.1856 +			}
  1.1857 +		}
  1.1858 +		e->count = count;
  1.1859 +		*type    = t;
  1.1860 +		return;
  1.1861 +		break;
  1.1862 +	}
  1.1863 +	case DW_TAG_subroutine_type:
  1.1864 +	{
  1.1865 +		Type *t = (Type *)calloc(sizeof(Type), 1);
  1.1866 +		t->type = TYPE_function;
  1.1867 +		FunctionType *f = (FunctionType *)calloc(sizeof(FunctionType), 1);
  1.1868 +		t->function = f;
  1.1869 +		elfAddType(t, unit, offset);
  1.1870 +		for (int i = 0; i < abbrev->numAttrs; i++)
  1.1871 +		{
  1.1872 +			ELFAttr *attr = &abbrev->attrs[i];
  1.1873 +			data = elfReadAttribute(data, attr);
  1.1874 +			switch (attr->name)
  1.1875 +			{
  1.1876 +			case DW_AT_prototyped:
  1.1877 +			case DW_AT_sibling:
  1.1878 +				break;
  1.1879 +			case DW_AT_type:
  1.1880 +				f->returnType = elfParseType(unit, attr->value);
  1.1881 +				break;
  1.1882 +			default:
  1.1883 +				fprintf(stderr, "Unknown subroutine attribute %02x\n", attr->name);
  1.1884 +			}
  1.1885 +		}
  1.1886 +		if (abbrev->hasChildren)
  1.1887 +		{
  1.1888 +			int bytes;
  1.1889 +			u32 num = elfReadLEB128(data, &bytes);
  1.1890 +			data += bytes;
  1.1891 +			Object *lastVar = NULL;
  1.1892 +			while (num)
  1.1893 +			{
  1.1894 +				ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
  1.1895 +
  1.1896 +				switch (abbr->tag)
  1.1897 +				{
  1.1898 +				case DW_TAG_formal_parameter:
  1.1899 +				{
  1.1900 +					Object *o;
  1.1901 +					data = elfParseObject(data, abbr, unit, &o);
  1.1902 +					if (f->args)
  1.1903 +						lastVar->next = o;
  1.1904 +					else
  1.1905 +						f->args = o;
  1.1906 +					lastVar = o;
  1.1907 +					break;
  1.1908 +				}
  1.1909 +				case DW_TAG_unspecified_parameters:
  1.1910 +					// no use in the debugger yet
  1.1911 +					data = elfSkipData(data, abbr, unit->abbrevs);
  1.1912 +					break;
  1.1913 +CASE_TYPE_TAG:
  1.1914 +					// skip types... parsed only when used
  1.1915 +					data = elfSkipData(data, abbr, unit->abbrevs);
  1.1916 +					break;
  1.1917 +				default:
  1.1918 +					fprintf(stderr, "Unknown subroutine tag %02x\n", abbr->tag);
  1.1919 +					data = elfSkipData(data, abbr, unit->abbrevs);
  1.1920 +					break;
  1.1921 +				}
  1.1922 +				num   = elfReadLEB128(data, &bytes);
  1.1923 +				data += bytes;
  1.1924 +			}
  1.1925 +		}
  1.1926 +		*type = t;
  1.1927 +		return;
  1.1928 +		break;
  1.1929 +	}
  1.1930 +	case DW_TAG_array_type:
  1.1931 +	{
  1.1932 +		u32    typeref = 0;
  1.1933 +		int    i;
  1.1934 +		Array *array = (Array *)calloc(sizeof(Array), 1);
  1.1935 +		Type * t     = (Type *)calloc(sizeof(Type), 1);
  1.1936 +		t->type = TYPE_array;
  1.1937 +		elfAddType(t, unit, offset);
  1.1938 +
  1.1939 +		for (i = 0; i < abbrev->numAttrs; i++)
  1.1940 +		{
  1.1941 +			ELFAttr *attr = &abbrev->attrs[i];
  1.1942 +			data = elfReadAttribute(data, attr);
  1.1943 +			switch (attr->name)
  1.1944 +			{
  1.1945 +			case DW_AT_sibling:
  1.1946 +				break;
  1.1947 +			case DW_AT_type:
  1.1948 +				typeref     = attr->value;
  1.1949 +				array->type = elfParseType(unit, typeref);
  1.1950 +				break;
  1.1951 +			default:
  1.1952 +				fprintf(stderr, "Unknown array attribute %02x\n", attr->name);
  1.1953 +			}
  1.1954 +		}
  1.1955 +		if (abbrev->hasChildren)
  1.1956 +		{
  1.1957 +			int bytes;
  1.1958 +			u32 num = elfReadLEB128(data, &bytes);
  1.1959 +			data += bytes;
  1.1960 +			int index     = 0;
  1.1961 +			int maxBounds = 0;
  1.1962 +			while (num)
  1.1963 +			{
  1.1964 +				ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
  1.1965 +
  1.1966 +				switch (abbr->tag)
  1.1967 +				{
  1.1968 +				case DW_TAG_subrange_type:
  1.1969 +				{
  1.1970 +					if (maxBounds == index)
  1.1971 +					{
  1.1972 +						maxBounds    += 4;
  1.1973 +						array->bounds = (int *)realloc(array->bounds,
  1.1974 +						                               sizeof(int)*maxBounds);
  1.1975 +					}
  1.1976 +					for (int i = 0; i < abbr->numAttrs; i++)
  1.1977 +					{
  1.1978 +						ELFAttr *attr = &abbr->attrs[i];
  1.1979 +						data = elfReadAttribute(data, attr);
  1.1980 +						switch (attr->name)
  1.1981 +						{
  1.1982 +						case DW_AT_upper_bound:
  1.1983 +							array->bounds[index] = attr->value+1;
  1.1984 +							break;
  1.1985 +						case DW_AT_type: // ignore
  1.1986 +							break;
  1.1987 +						default:
  1.1988 +							fprintf(stderr, "Unknown subrange attribute %02x\n",
  1.1989 +							        attr->name);
  1.1990 +						}
  1.1991 +					}
  1.1992 +					index++;
  1.1993 +					break;
  1.1994 +				}
  1.1995 +				default:
  1.1996 +					fprintf(stderr, "Unknown array tag %02x\n", abbr->tag);
  1.1997 +					data = elfSkipData(data, abbr, unit->abbrevs);
  1.1998 +					break;
  1.1999 +				}
  1.2000 +				num   = elfReadLEB128(data, &bytes);
  1.2001 +				data += bytes;
  1.2002 +			}
  1.2003 +			array->maxBounds = index;
  1.2004 +		}
  1.2005 +		t->size = array->type->size;
  1.2006 +		for (i = 0; i < array->maxBounds; i++)
  1.2007 +			t->size *= array->bounds[i];
  1.2008 +		t->array = array;
  1.2009 +		*type    = t;
  1.2010 +		return;
  1.2011 +		break;
  1.2012 +	}
  1.2013 +	default:
  1.2014 +		fprintf(stderr, "Unknown type TAG %02x\n", abbrev->tag);
  1.2015 +		exit(-1);
  1.2016 +	}
  1.2017 +}
  1.2018 +
  1.2019 +Type *elfParseType(CompileUnit *unit, u32 offset)
  1.2020 +{
  1.2021 +	Type *t = unit->types;
  1.2022 +
  1.2023 +	while (t)
  1.2024 +	{
  1.2025 +		if (t->offset == offset)
  1.2026 +			return t;
  1.2027 +		t = t->next;
  1.2028 +	}
  1.2029 +	if (offset == 0)
  1.2030 +	{
  1.2031 +		Type *t = (Type *)calloc(sizeof(Type), 1);
  1.2032 +		t->type   = TYPE_void;
  1.2033 +		t->offset = 0;
  1.2034 +		elfAddType(t, unit, 0);
  1.2035 +		return t;
  1.2036 +	}
  1.2037 +	u8 *data = unit->top + offset;
  1.2038 +	int bytes;
  1.2039 +	int abbrevNum = elfReadLEB128(data, &bytes);
  1.2040 +	data += bytes;
  1.2041 +	Type *type = NULL;
  1.2042 +
  1.2043 +	ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
  1.2044 +
  1.2045 +	elfParseType(data, offset, abbrev, unit, &type);
  1.2046 +	return type;
  1.2047 +}
  1.2048 +
  1.2049 +void elfGetObjectAttributes(CompileUnit *unit, u32 offset, Object *o)
  1.2050 +{
  1.2051 +	u8 *data = unit->top + offset;
  1.2052 +	int bytes;
  1.2053 +	u32 abbrevNum = elfReadLEB128(data, &bytes);
  1.2054 +	data += bytes;
  1.2055 +
  1.2056 +	if (!abbrevNum)
  1.2057 +	{
  1.2058 +		return;
  1.2059 +	}
  1.2060 +
  1.2061 +	ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
  1.2062 +
  1.2063 +	for (int i = 0; i < abbrev->numAttrs; i++)
  1.2064 +	{
  1.2065 +		ELFAttr *attr = &abbrev->attrs[i];
  1.2066 +		data = elfReadAttribute(data, attr);
  1.2067 +		switch (attr->name)
  1.2068 +		{
  1.2069 +		case DW_AT_location:
  1.2070 +			o->location = attr->block;
  1.2071 +			break;
  1.2072 +		case DW_AT_name:
  1.2073 +			if (o->name == NULL)
  1.2074 +				o->name = attr->string;
  1.2075 +			break;
  1.2076 +		case DW_AT_MIPS_linkage_name:
  1.2077 +			o->name = attr->string;
  1.2078 +			break;
  1.2079 +		case DW_AT_decl_file:
  1.2080 +			o->file = attr->value;
  1.2081 +			break;
  1.2082 +		case DW_AT_decl_line:
  1.2083 +			o->line = attr->value;
  1.2084 +			break;
  1.2085 +		case DW_AT_type:
  1.2086 +			o->type = elfParseType(unit, attr->value);
  1.2087 +			break;
  1.2088 +		case DW_AT_external:
  1.2089 +			o->external = attr->flag;
  1.2090 +			break;
  1.2091 +		case DW_AT_const_value:
  1.2092 +		case DW_AT_abstract_origin:
  1.2093 +		case DW_AT_declaration:
  1.2094 +		case DW_AT_artificial:
  1.2095 +			// todo
  1.2096 +			break;
  1.2097 +		case DW_AT_specification:
  1.2098 +			// TODO:
  1.2099 +			break;
  1.2100 +		default:
  1.2101 +			fprintf(stderr, "Unknown object attribute %02x\n", attr->name);
  1.2102 +			break;
  1.2103 +		}
  1.2104 +	}
  1.2105 +}
  1.2106 +
  1.2107 +u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
  1.2108 +                   Object **object)
  1.2109 +{
  1.2110 +	Object *o = (Object *)calloc(sizeof(Object), 1);
  1.2111 +
  1.2112 +	o->next = NULL;
  1.2113 +
  1.2114 +	for (int i = 0; i < abbrev->numAttrs; i++)
  1.2115 +	{
  1.2116 +		ELFAttr *attr = &abbrev->attrs[i];
  1.2117 +		data = elfReadAttribute(data, attr);
  1.2118 +		switch (attr->name)
  1.2119 +		{
  1.2120 +		case DW_AT_location:
  1.2121 +			o->location = attr->block;
  1.2122 +			break;
  1.2123 +		case DW_AT_name:
  1.2124 +			if (o->name == NULL)
  1.2125 +				o->name = attr->string;
  1.2126 +			break;
  1.2127 +		case DW_AT_MIPS_linkage_name:
  1.2128 +			o->name = attr->string;
  1.2129 +			break;
  1.2130 +		case DW_AT_decl_file:
  1.2131 +			o->file = attr->value;
  1.2132 +			break;
  1.2133 +		case DW_AT_decl_line:
  1.2134 +			o->line = attr->value;
  1.2135 +			break;
  1.2136 +		case DW_AT_type:
  1.2137 +			o->type = elfParseType(unit, attr->value);
  1.2138 +			break;
  1.2139 +		case DW_AT_external:
  1.2140 +			o->external = attr->flag;
  1.2141 +			break;
  1.2142 +		case DW_AT_abstract_origin:
  1.2143 +			elfGetObjectAttributes(unit, attr->value, o);
  1.2144 +			break;
  1.2145 +		case DW_AT_const_value:
  1.2146 +		case DW_AT_declaration:
  1.2147 +		case DW_AT_artificial:
  1.2148 +			break;
  1.2149 +		case DW_AT_specification:
  1.2150 +			// TODO:
  1.2151 +			break;
  1.2152 +		default:
  1.2153 +			fprintf(stderr, "Unknown object attribute %02x\n", attr->name);
  1.2154 +			break;
  1.2155 +		}
  1.2156 +	}
  1.2157 +	*object = o;
  1.2158 +	return data;
  1.2159 +}
  1.2160 +
  1.2161 +u8 *elfParseBlock(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
  1.2162 +                  Function *func, Object **lastVar)
  1.2163 +{
  1.2164 +	int bytes;
  1.2165 +	u32 start = func->lowPC;
  1.2166 +	u32 end   = func->highPC;
  1.2167 +
  1.2168 +	for (int i = 0; i < abbrev->numAttrs; i++)
  1.2169 +	{
  1.2170 +		ELFAttr *attr = &abbrev->attrs[i];
  1.2171 +		data = elfReadAttribute(data, attr);
  1.2172 +		switch (attr->name)
  1.2173 +		{
  1.2174 +		case DW_AT_sibling:
  1.2175 +			break;
  1.2176 +		case DW_AT_low_pc:
  1.2177 +			start = attr->value;
  1.2178 +			break;
  1.2179 +		case DW_AT_high_pc:
  1.2180 +			end = attr->value;
  1.2181 +			break;
  1.2182 +		case DW_AT_ranges: // ignore for now
  1.2183 +			break;
  1.2184 +		default:
  1.2185 +			fprintf(stderr, "Unknown block attribute %02x\n", attr->name);
  1.2186 +			break;
  1.2187 +		}
  1.2188 +	}
  1.2189 +
  1.2190 +	if (abbrev->hasChildren)
  1.2191 +	{
  1.2192 +		int nesting = 1;
  1.2193 +
  1.2194 +		while (nesting)
  1.2195 +		{
  1.2196 +			u32 abbrevNum = elfReadLEB128(data, &bytes);
  1.2197 +			data += bytes;
  1.2198 +
  1.2199 +			if (!abbrevNum)
  1.2200 +			{
  1.2201 +				nesting--;
  1.2202 +				continue;
  1.2203 +			}
  1.2204 +
  1.2205 +			abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
  1.2206 +
  1.2207 +			switch (abbrev->tag)
  1.2208 +			{
  1.2209 +CASE_TYPE_TAG:       // types only parsed when used
  1.2210 +			case DW_TAG_label: // not needed
  1.2211 +				data = elfSkipData(data, abbrev, unit->abbrevs);
  1.2212 +				break;
  1.2213 +			case DW_TAG_lexical_block:
  1.2214 +				data = elfParseBlock(data, abbrev, unit, func, lastVar);
  1.2215 +				break;
  1.2216 +			case DW_TAG_subprogram:
  1.2217 +			{
  1.2218 +				Function *f = NULL;
  1.2219 +				data = elfParseFunction(data, abbrev, unit, &f);
  1.2220 +				if (f != NULL)
  1.2221 +				{
  1.2222 +					if (unit->lastFunction)
  1.2223 +						unit->lastFunction->next = f;
  1.2224 +					else
  1.2225 +						unit->functions = f;
  1.2226 +					unit->lastFunction = f;
  1.2227 +				}
  1.2228 +				break;
  1.2229 +			}
  1.2230 +			case DW_TAG_variable:
  1.2231 +			{
  1.2232 +				Object *o;
  1.2233 +				data = elfParseObject(data, abbrev, unit, &o);
  1.2234 +				if (o->startScope == 0)
  1.2235 +					o->startScope = start;
  1.2236 +				if (o->endScope == 0)
  1.2237 +					o->endScope = 0;
  1.2238 +				if (func->variables)
  1.2239 +					(*lastVar)->next = o;
  1.2240 +				else
  1.2241 +					func->variables = o;
  1.2242 +				*lastVar = o;
  1.2243 +				break;
  1.2244 +			}
  1.2245 +			case DW_TAG_inlined_subroutine:
  1.2246 +				// TODO:
  1.2247 +				data = elfSkipData(data, abbrev, unit->abbrevs);
  1.2248 +				break;
  1.2249 +			default:
  1.2250 +			{
  1.2251 +				fprintf(stderr, "Unknown block TAG %02x\n", abbrev->tag);
  1.2252 +				data = elfSkipData(data, abbrev, unit->abbrevs);
  1.2253 +				break;
  1.2254 +			}
  1.2255 +			}
  1.2256 +		}
  1.2257 +	}
  1.2258 +	return data;
  1.2259 +}
  1.2260 +
  1.2261 +void elfGetFunctionAttributes(CompileUnit *unit, u32 offset, Function *func)
  1.2262 +{
  1.2263 +	u8 *data = unit->top + offset;
  1.2264 +	int bytes;
  1.2265 +	u32 abbrevNum = elfReadLEB128(data, &bytes);
  1.2266 +	data += bytes;
  1.2267 +
  1.2268 +	if (!abbrevNum)
  1.2269 +	{
  1.2270 +		return;
  1.2271 +	}
  1.2272 +
  1.2273 +	ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
  1.2274 +
  1.2275 +	for (int i = 0; i < abbrev->numAttrs; i++)
  1.2276 +	{
  1.2277 +		ELFAttr *attr = &abbrev->attrs[i];
  1.2278 +		data = elfReadAttribute(data, attr);
  1.2279 +
  1.2280 +		switch (attr->name)
  1.2281 +		{
  1.2282 +		case DW_AT_sibling:
  1.2283 +			break;
  1.2284 +		case DW_AT_name:
  1.2285 +			if (func->name == NULL)
  1.2286 +				func->name = attr->string;
  1.2287 +			break;
  1.2288 +		case DW_AT_MIPS_linkage_name:
  1.2289 +			func->name = attr->string;
  1.2290 +			break;
  1.2291 +		case DW_AT_low_pc:
  1.2292 +			func->lowPC = attr->value;
  1.2293 +			break;
  1.2294 +		case DW_AT_high_pc:
  1.2295 +			func->highPC = attr->value;
  1.2296 +			break;
  1.2297 +		case DW_AT_decl_file:
  1.2298 +			func->file = attr->value;
  1.2299 +			break;
  1.2300 +		case DW_AT_decl_line:
  1.2301 +			func->line = attr->value;
  1.2302 +			break;
  1.2303 +		case DW_AT_external:
  1.2304 +			func->external = attr->flag;
  1.2305 +			break;
  1.2306 +		case DW_AT_frame_base:
  1.2307 +			func->frameBase = attr->block;
  1.2308 +			break;
  1.2309 +		case DW_AT_type:
  1.2310 +			func->returnType = elfParseType(unit, attr->value);
  1.2311 +			break;
  1.2312 +		case DW_AT_inline:
  1.2313 +		case DW_AT_specification:
  1.2314 +		case DW_AT_declaration:
  1.2315 +		case DW_AT_artificial:
  1.2316 +		case DW_AT_prototyped:
  1.2317 +		case DW_AT_proc_body:
  1.2318 +		case DW_AT_save_offset:
  1.2319 +		case DW_AT_user_2002:
  1.2320 +		case DW_AT_virtuality:
  1.2321 +		case DW_AT_containing_type:
  1.2322 +		case DW_AT_accessibility:
  1.2323 +			// todo;
  1.2324 +			break;
  1.2325 +		case DW_AT_vtable_elem_location:
  1.2326 +			free(attr->block);
  1.2327 +			break;
  1.2328 +		default:
  1.2329 +			fprintf(stderr, "Unknown function attribute %02x\n", attr->name);
  1.2330 +			break;
  1.2331 +		}
  1.2332 +	}
  1.2333 +
  1.2334 +	return;
  1.2335 +}
  1.2336 +
  1.2337 +u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
  1.2338 +                     Function **f)
  1.2339 +{
  1.2340 +	Function *func = (Function *)calloc(sizeof(Function), 1);
  1.2341 +	*f = func;
  1.2342 +
  1.2343 +	int  bytes;
  1.2344 +	bool mangled     = false;
  1.2345 +	bool declaration = false;
  1.2346 +	for (int i = 0; i < abbrev->numAttrs; i++)
  1.2347 +	{
  1.2348 +		ELFAttr *attr = &abbrev->attrs[i];
  1.2349 +		data = elfReadAttribute(data, attr);
  1.2350 +		switch (attr->name)
  1.2351 +		{
  1.2352 +		case DW_AT_sibling:
  1.2353 +			break;
  1.2354 +		case DW_AT_name:
  1.2355 +			if (func->name == NULL)
  1.2356 +				func->name = attr->string;
  1.2357 +			break;
  1.2358 +		case DW_AT_MIPS_linkage_name:
  1.2359 +			func->name = attr->string;
  1.2360 +			mangled    = true;
  1.2361 +			break;
  1.2362 +		case DW_AT_low_pc:
  1.2363 +			func->lowPC = attr->value;
  1.2364 +			break;
  1.2365 +		case DW_AT_high_pc:
  1.2366 +			func->highPC = attr->value;
  1.2367 +			break;
  1.2368 +		case DW_AT_prototyped:
  1.2369 +			break;
  1.2370 +		case DW_AT_decl_file:
  1.2371 +			func->file = attr->value;
  1.2372 +			break;
  1.2373 +		case DW_AT_decl_line:
  1.2374 +			func->line = attr->value;
  1.2375 +			break;
  1.2376 +		case DW_AT_external:
  1.2377 +			func->external = attr->flag;
  1.2378 +			break;
  1.2379 +		case DW_AT_frame_base:
  1.2380 +			func->frameBase = attr->block;
  1.2381 +			break;
  1.2382 +		case DW_AT_type:
  1.2383 +			func->returnType = elfParseType(unit, attr->value);
  1.2384 +			break;
  1.2385 +		case DW_AT_abstract_origin:
  1.2386 +			elfGetFunctionAttributes(unit, attr->value, func);
  1.2387 +			break;
  1.2388 +		case DW_AT_declaration:
  1.2389 +			declaration = attr->flag;
  1.2390 +			break;
  1.2391 +		case DW_AT_inline:
  1.2392 +		case DW_AT_specification:
  1.2393 +		case DW_AT_artificial:
  1.2394 +		case DW_AT_proc_body:
  1.2395 +		case DW_AT_save_offset:
  1.2396 +		case DW_AT_user_2002:
  1.2397 +		case DW_AT_virtuality:
  1.2398 +		case DW_AT_containing_type:
  1.2399 +		case DW_AT_accessibility:
  1.2400 +			// todo;
  1.2401 +			break;
  1.2402 +		case DW_AT_vtable_elem_location:
  1.2403 +			free(attr->block);
  1.2404 +			break;
  1.2405 +		default:
  1.2406 +			fprintf(stderr, "Unknown function attribute %02x\n", attr->name);
  1.2407 +			break;
  1.2408 +		}
  1.2409 +	}
  1.2410 +
  1.2411 +	if (declaration)
  1.2412 +	{
  1.2413 +		elfCleanUp(func);
  1.2414 +		free(func);
  1.2415 +		*f = NULL;
  1.2416 +
  1.2417 +		while (1)
  1.2418 +		{
  1.2419 +			u32 abbrevNum = elfReadLEB128(data, &bytes);
  1.2420 +			data += bytes;
  1.2421 +
  1.2422 +			if (!abbrevNum)
  1.2423 +			{
  1.2424 +				return data;
  1.2425 +			}
  1.2426 +
  1.2427 +			abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
  1.2428 +
  1.2429 +			data = elfSkipData(data, abbrev, unit->abbrevs);
  1.2430 +		}
  1.2431 +	}
  1.2432 +
  1.2433 +	if (abbrev->hasChildren)
  1.2434 +	{
  1.2435 +		int     nesting   = 1;
  1.2436 +		Object *lastParam = NULL;
  1.2437 +		Object *lastVar   = NULL;
  1.2438 +
  1.2439 +		while (nesting)
  1.2440 +		{
  1.2441 +			u32 abbrevNum = elfReadLEB128(data, &bytes);
  1.2442 +			data += bytes;
  1.2443 +
  1.2444 +			if (!abbrevNum)
  1.2445 +			{
  1.2446 +				nesting--;
  1.2447 +				continue;
  1.2448 +			}
  1.2449 +
  1.2450 +			abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
  1.2451 +
  1.2452 +			switch (abbrev->tag)
  1.2453 +			{
  1.2454 +CASE_TYPE_TAG:       // no need to parse types. only parsed when used
  1.2455 +			case DW_TAG_label: // not needed
  1.2456 +				data = elfSkipData(data, abbrev, unit->abbrevs);
  1.2457 +				break;
  1.2458 +			case DW_TAG_subprogram:
  1.2459 +			{
  1.2460 +				Function *fnc = NULL;
  1.2461 +				data = elfParseFunction(data, abbrev, unit, &fnc);
  1.2462 +				if (fnc != NULL)
  1.2463 +				{
  1.2464 +					if (unit->lastFunction == NULL)
  1.2465 +						unit->functions = fnc;
  1.2466 +					else
  1.2467 +						unit->lastFunction->next = fnc;
  1.2468 +					unit->lastFunction = fnc;
  1.2469 +				}
  1.2470 +				break;
  1.2471 +			}
  1.2472 +			case DW_TAG_lexical_block:
  1.2473 +			{
  1.2474 +				data = elfParseBlock(data, abbrev, unit, func, &lastVar);
  1.2475 +				break;
  1.2476 +			}
  1.2477 +			case DW_TAG_formal_parameter:
  1.2478 +			{
  1.2479 +				Object *o;
  1.2480 +				data = elfParseObject(data, abbrev, unit, &o);
  1.2481 +				if (func->parameters)
  1.2482 +					lastParam->next = o;
  1.2483 +				else
  1.2484 +					func->parameters = o;
  1.2485 +				lastParam = o;
  1.2486 +				break;
  1.2487 +			}
  1.2488 +			case DW_TAG_variable:
  1.2489 +			{
  1.2490 +				Object *o;
  1.2491 +				data = elfParseObject(data, abbrev, unit, &o);
  1.2492 +				if (func->variables)
  1.2493 +					lastVar->next = o;
  1.2494 +				else
  1.2495 +					func->variables = o;
  1.2496 +				lastVar = o;
  1.2497 +				break;
  1.2498 +			}
  1.2499 +			case DW_TAG_unspecified_parameters:
  1.2500 +			case DW_TAG_inlined_subroutine:
  1.2501 +			{
  1.2502 +				// todo
  1.2503 +				for (int i = 0; i < abbrev->numAttrs; i++)
  1.2504 +				{
  1.2505 +					data = elfReadAttribute(data,  &abbrev->attrs[i]);
  1.2506 +					if (abbrev->attrs[i].form == DW_FORM_block1)
  1.2507 +						free(abbrev->attrs[i].block);
  1.2508 +				}
  1.2509 +
  1.2510 +				if (abbrev->hasChildren)
  1.2511 +					nesting++;
  1.2512 +				break;
  1.2513 +			}
  1.2514 +			default:
  1.2515 +			{
  1.2516 +				fprintf(stderr, "Unknown function TAG %02x\n", abbrev->tag);
  1.2517 +				data = elfSkipData(data, abbrev, unit->abbrevs);
  1.2518 +				break;
  1.2519 +			}
  1.2520 +			}
  1.2521 +		}
  1.2522 +	}
  1.2523 +	return data;
  1.2524 +}
  1.2525 +
  1.2526 +u8 *elfParseUnknownData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs)
  1.2527 +{
  1.2528 +	int i;
  1.2529 +	int bytes;
  1.2530 +	//  switch(abbrev->tag) {
  1.2531 +	//  default:
  1.2532 +	fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag);
  1.2533 +
  1.2534 +	for (i = 0; i < abbrev->numAttrs; i++)
  1.2535 +	{
  1.2536 +		data = elfReadAttribute(data,  &abbrev->attrs[i]);
  1.2537 +		if (abbrev->attrs[i].form == DW_FORM_block1)
  1.2538 +			free(abbrev->attrs[i].block);
  1.2539 +	}
  1.2540 +
  1.2541 +	if (abbrev->hasChildren)
  1.2542 +	{
  1.2543 +		int nesting = 1;
  1.2544 +		while (nesting)
  1.2545 +		{
  1.2546 +			u32 abbrevNum = elfReadLEB128(data, &bytes);
  1.2547 +			data += bytes;
  1.2548 +
  1.2549 +			if (!abbrevNum)
  1.2550 +			{
  1.2551 +				nesting--;
  1.2552 +				continue;
  1.2553 +			}
  1.2554 +
  1.2555 +			abbrev = elfGetAbbrev(abbrevs, abbrevNum);
  1.2556 +
  1.2557 +			fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag);
  1.2558 +
  1.2559 +			for (i = 0; i < abbrev->numAttrs; i++)
  1.2560 +			{
  1.2561 +				data = elfReadAttribute(data,  &abbrev->attrs[i]);
  1.2562 +				if (abbrev->attrs[i].form == DW_FORM_block1)
  1.2563 +					free(abbrev->attrs[i].block);
  1.2564 +			}
  1.2565 +
  1.2566 +			if (abbrev->hasChildren)
  1.2567 +			{
  1.2568 +				nesting++;
  1.2569 +			}
  1.2570 +		}
  1.2571 +	}
  1.2572 +	//  }
  1.2573 +	return data;
  1.2574 +}
  1.2575 +
  1.2576 +u8 *elfParseCompileUnitChildren(u8 *data, CompileUnit *unit)
  1.2577 +{
  1.2578 +	int bytes;
  1.2579 +	u32 abbrevNum = elfReadLEB128(data, &bytes);
  1.2580 +	data += bytes;
  1.2581 +	Object *lastObj = NULL;
  1.2582 +	while (abbrevNum)
  1.2583 +	{
  1.2584 +		ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
  1.2585 +		switch (abbrev->tag)
  1.2586 +		{
  1.2587 +		case DW_TAG_subprogram:
  1.2588 +		{
  1.2589 +			Function *func = NULL;
  1.2590 +			data = elfParseFunction(data, abbrev, unit, &func);
  1.2591 +			if (func != NULL)
  1.2592 +			{
  1.2593 +				if (unit->lastFunction)
  1.2594 +					unit->lastFunction->next = func;
  1.2595 +				else
  1.2596 +					unit->functions = func;
  1.2597 +				unit->lastFunction = func;
  1.2598 +			}
  1.2599 +			break;
  1.2600 +		}
  1.2601 +CASE_TYPE_TAG:
  1.2602 +			data = elfSkipData(data, abbrev, unit->abbrevs);
  1.2603 +			break;
  1.2604 +		case DW_TAG_variable:
  1.2605 +		{
  1.2606 +			Object *var = NULL;
  1.2607 +			data = elfParseObject(data, abbrev, unit, &var);
  1.2608 +			if (lastObj)
  1.2609 +				lastObj->next = var;
  1.2610 +			else
  1.2611 +				unit->variables = var;
  1.2612 +			lastObj = var;
  1.2613 +			break;
  1.2614 +		}
  1.2615 +		default:
  1.2616 +			data = elfParseUnknownData(data, abbrev, unit->abbrevs);
  1.2617 +			break;
  1.2618 +		}
  1.2619 +
  1.2620 +		abbrevNum = elfReadLEB128(data, &bytes);
  1.2621 +		data     += bytes;
  1.2622 +	}
  1.2623 +	return data;
  1.2624 +}
  1.2625 +
  1.2626 +CompileUnit *elfParseCompUnit(u8 *data, u8 *abbrevData)
  1.2627 +{
  1.2628 +	int bytes;
  1.2629 +	u8 *top = data;
  1.2630 +
  1.2631 +	u32 length = elfRead4Bytes(data);
  1.2632 +	data += 4;
  1.2633 +
  1.2634 +	u16 version = elfRead2Bytes(data);
  1.2635 +	data += 2;
  1.2636 +
  1.2637 +	u32 offset = elfRead4Bytes(data);
  1.2638 +	data += 4;
  1.2639 +
  1.2640 +	u8 addrSize = *data++;
  1.2641 +
  1.2642 +	if (version != 2)
  1.2643 +	{
  1.2644 +		fprintf(stderr, "Unsupported debugging information version %d\n", version);
  1.2645 +		return NULL;
  1.2646 +	}
  1.2647 +
  1.2648 +	if (addrSize != 4)
  1.2649 +	{
  1.2650 +		fprintf(stderr, "Unsupported address size %d\n", addrSize);
  1.2651 +		return NULL;
  1.2652 +	}
  1.2653 +
  1.2654 +	ELFAbbrev **abbrevs = elfReadAbbrevs(abbrevData, offset);
  1.2655 +
  1.2656 +	u32 abbrevNum = elfReadLEB128(data, &bytes);
  1.2657 +	data += bytes;
  1.2658 +
  1.2659 +	ELFAbbrev *abbrev = elfGetAbbrev(abbrevs, abbrevNum);
  1.2660 +
  1.2661 +	CompileUnit *unit = (CompileUnit *)calloc(sizeof(CompileUnit), 1);
  1.2662 +	unit->top     = top;
  1.2663 +	unit->length  = length;
  1.2664 +	unit->abbrevs = abbrevs;
  1.2665 +	unit->next    = NULL;
  1.2666 +
  1.2667 +	elfCurrentUnit = unit;
  1.2668 +
  1.2669 +	int i;
  1.2670 +
  1.2671 +	for (i = 0; i < abbrev->numAttrs; i++)
  1.2672 +	{
  1.2673 +		ELFAttr *attr = &abbrev->attrs[i];
  1.2674 +		data = elfReadAttribute(data, attr);
  1.2675 +
  1.2676 +		switch (attr->name)
  1.2677 +		{
  1.2678 +		case DW_AT_name:
  1.2679 +			unit->name = attr->string;
  1.2680 +			break;
  1.2681 +		case DW_AT_stmt_list:
  1.2682 +			unit->hasLineInfo = true;
  1.2683 +			unit->lineInfo    = attr->value;
  1.2684 +			break;
  1.2685 +		case DW_AT_low_pc:
  1.2686 +			unit->lowPC = attr->value;
  1.2687 +			break;
  1.2688 +		case DW_AT_high_pc:
  1.2689 +			unit->highPC = attr->value;
  1.2690 +			break;
  1.2691 +		case DW_AT_compdir:
  1.2692 +			unit->compdir = attr->string;
  1.2693 +			break;
  1.2694 +		// ignore
  1.2695 +		case DW_AT_language:
  1.2696 +		case DW_AT_producer:
  1.2697 +		case DW_AT_macro_info:
  1.2698 +		case DW_AT_entry_pc:
  1.2699 +			break;
  1.2700 +		default:
  1.2701 +			fprintf(stderr, "Unknown attribute %02x\n", attr->name);
  1.2702 +			break;
  1.2703 +		}
  1.2704 +	}
  1.2705 +
  1.2706 +	if (abbrev->hasChildren)
  1.2707 +		elfParseCompileUnitChildren(data, unit);
  1.2708 +
  1.2709 +	return unit;
  1.2710 +}
  1.2711 +
  1.2712 +void elfParseAranges(u8 *data)
  1.2713 +{
  1.2714 +	ELFSectionHeader *sh = elfGetSectionByName(".debug_aranges");
  1.2715 +	if (sh == NULL)
  1.2716 +	{
  1.2717 +		fprintf(stderr, "No aranges found\n");
  1.2718 +		return;
  1.2719 +	}
  1.2720 +
  1.2721 +	data = elfReadSection(data, sh);
  1.2722 +	u8 *end = data + READ32LE(&sh->size);
  1.2723 +
  1.2724 +	int      max    = 4;
  1.2725 +	ARanges *ranges = (ARanges *)calloc(sizeof(ARanges), 4);
  1.2726 +
  1.2727 +	int index = 0;
  1.2728 +
  1.2729 +	while (data < end)
  1.2730 +	{
  1.2731 +		u32 len = elfRead4Bytes(data);
  1.2732 +		data += 4;
  1.2733 +		//    u16 version = elfRead2Bytes(data);
  1.2734 +		data += 2;
  1.2735 +		u32 offset = elfRead4Bytes(data);
  1.2736 +		data += 4;
  1.2737 +		//    u8 addrSize = *data++;
  1.2738 +		//    u8 segSize = *data++;
  1.2739 +		data += 2; // remove if uncommenting above
  1.2740 +		data += 4;
  1.2741 +		ranges[index].count  = (len-20)/8;
  1.2742 +		ranges[index].offset = offset;
  1.2743 +		ranges[index].ranges = (ARange *)calloc(sizeof(ARange), (len-20)/8);
  1.2744 +		int i = 0;
  1.2745 +		while (true)
  1.2746 +		{
  1.2747 +			u32 addr = elfRead4Bytes(data);
  1.2748 +			data += 4;
  1.2749 +			u32 len = elfRead4Bytes(data);
  1.2750 +			data += 4;
  1.2751 +			if (addr == 0 && len == 0)
  1.2752 +				break;
  1.2753 +			ranges[index].ranges[i].lowPC  = addr;
  1.2754 +			ranges[index].ranges[i].highPC = addr+len;
  1.2755 +			i++;
  1.2756 +		}
  1.2757 +		index++;
  1.2758 +		if (index == max)
  1.2759 +		{
  1.2760 +			max   += 4;
  1.2761 +			ranges = (ARanges *)realloc(ranges, max*sizeof(ARanges));
  1.2762 +		}
  1.2763 +	}
  1.2764 +	elfDebugInfo->numRanges = index;
  1.2765 +	elfDebugInfo->ranges    = ranges;
  1.2766 +}
  1.2767 +
  1.2768 +void elfReadSymtab(u8 *data)
  1.2769 +{
  1.2770 +	ELFSectionHeader *sh = elfGetSectionByName(".symtab");
  1.2771 +	int table = READ32LE(&sh->link);
  1.2772 +
  1.2773 +	char *strtable = (char *)elfReadSection(data, elfGetSectionByNumber(table));
  1.2774 +
  1.2775 +	ELFSymbol *symtab = (ELFSymbol *)elfReadSection(data, sh);
  1.2776 +
  1.2777 +	int count = READ32LE(&sh->size) / sizeof(ELFSymbol);
  1.2778 +	elfSymbolsCount = 0;
  1.2779 +
  1.2780 +	elfSymbols = (Symbol *)malloc(sizeof(Symbol)*count);
  1.2781 +
  1.2782 +	int i;
  1.2783 +
  1.2784 +	for (i = 0; i < count; i++)
  1.2785 +	{
  1.2786 +		ELFSymbol *s       = &symtab[i];
  1.2787 +		int        type    = s->info & 15;
  1.2788 +		int        binding = s->info >> 4;
  1.2789 +
  1.2790 +		if (binding)
  1.2791 +		{
  1.2792 +			Symbol *sym = &elfSymbols[elfSymbolsCount];
  1.2793 +			sym->name    = &strtable[READ32LE(&s->name)];
  1.2794 +			sym->binding = binding;
  1.2795 +			sym->type    = type;
  1.2796 +			sym->value   = READ32LE(&s->value);
  1.2797 +			sym->size    = READ32LE(&s->size);
  1.2798 +			elfSymbolsCount++;
  1.2799 +		}
  1.2800 +	}
  1.2801 +	for (i = 0; i < count; i++)
  1.2802 +	{
  1.2803 +		ELFSymbol *s    = &symtab[i];
  1.2804 +		int        bind = s->info>>4;
  1.2805 +		int        type = s->info & 15;
  1.2806 +
  1.2807 +		if (!bind)
  1.2808 +		{
  1.2809 +			Symbol *sym = &elfSymbols[elfSymbolsCount];
  1.2810 +			sym->name    = &strtable[READ32LE(&s->name)];
  1.2811 +			sym->binding = (s->info >> 4);
  1.2812 +			sym->type    = type;
  1.2813 +			sym->value   = READ32LE(&s->value);
  1.2814 +			sym->size    = READ32LE(&s->size);
  1.2815 +			elfSymbolsCount++;
  1.2816 +		}
  1.2817 +	}
  1.2818 +	elfSymbolsStrTab = strtable;
  1.2819 +	//  free(symtab);
  1.2820 +}
  1.2821 +
  1.2822 +bool elfReadProgram(ELFHeader *eh, u8 *data, int& size, bool parseDebug)
  1.2823 +{
  1.2824 +	int count = READ16LE(&eh->e_phnum);
  1.2825 +	int i;
  1.2826 +
  1.2827 +	if (READ32LE(&eh->e_entry) == 0x2000000)
  1.2828 +		cpuIsMultiBoot = true;
  1.2829 +
  1.2830 +	// read program headers... should probably move this code down
  1.2831 +	u8 *p = data + READ32LE(&eh->e_phoff);
  1.2832 +	size = 0;
  1.2833 +	for (i = 0; i < count; i++)
  1.2834 +	{
  1.2835 +		ELFProgramHeader *ph = (ELFProgramHeader *)p;
  1.2836 +		p += sizeof(ELFProgramHeader);
  1.2837 +		if (READ16LE(&eh->e_phentsize) != sizeof(ELFProgramHeader))
  1.2838 +		{
  1.2839 +			p += READ16LE(&eh->e_phentsize) - sizeof(ELFProgramHeader);
  1.2840 +		}
  1.2841 +
  1.2842 +		//    printf("PH %d %08x %08x %08x %08x %08x %08x %08x %08x\n",
  1.2843 +		//     i, ph->type, ph->offset, ph->vaddr, ph->paddr,
  1.2844 +		//     ph->filesz, ph->memsz, ph->flags, ph->align);
  1.2845 +		if (cpuIsMultiBoot)
  1.2846 +		{
  1.2847 +			if (READ32LE(&ph->paddr) >= 0x2000000 &&
  1.2848 +			    READ32LE(&ph->paddr) <= 0x203ffff)
  1.2849 +			{
  1.2850 +				memcpy(&workRAM[READ32LE(&ph->paddr) & 0x3ffff],
  1.2851 +				       data + READ32LE(&ph->offset),
  1.2852 +				       READ32LE(&ph->filesz));
  1.2853 +			}
  1.2854 +		}
  1.2855 +		else
  1.2856 +		{
  1.2857 +			if (READ32LE(&ph->paddr) >= 0x8000000 &&
  1.2858 +			    READ32LE(&ph->paddr) <= 0x9ffffff)
  1.2859 +			{
  1.2860 +				memcpy(&rom[READ32LE(&ph->paddr) & 0x1ffffff],
  1.2861 +				       data + READ32LE(&ph->offset),
  1.2862 +				       READ32LE(&ph->filesz));
  1.2863 +				size += READ32LE(&ph->filesz);
  1.2864 +			}
  1.2865 +		}
  1.2866 +	}
  1.2867 +
  1.2868 +	char *stringTable = NULL;
  1.2869 +
  1.2870 +	// read section headers
  1.2871 +	p     = data + READ32LE(&eh->e_shoff);
  1.2872 +	count = READ16LE(&eh->e_shnum);
  1.2873 +
  1.2874 +	ELFSectionHeader **sh = (ELFSectionHeader * *)
  1.2875 +	                        malloc(sizeof(ELFSectionHeader *) * count);
  1.2876 +
  1.2877 +	for (i = 0; i < count; i++)
  1.2878 +	{
  1.2879 +		sh[i] = (ELFSectionHeader *)p;
  1.2880 +		p    += sizeof(ELFSectionHeader);
  1.2881 +		if (READ16LE(&eh->e_shentsize) != sizeof(ELFSectionHeader))
  1.2882 +			p += READ16LE(&eh->e_shentsize) - sizeof(ELFSectionHeader);
  1.2883 +	}
  1.2884 +
  1.2885 +	if (READ16LE(&eh->e_shstrndx) != 0)
  1.2886 +	{
  1.2887 +		stringTable = (char *)elfReadSection(data,
  1.2888 +		                                     sh[READ16LE(&eh->e_shstrndx)]);
  1.2889 +	}
  1.2890 +
  1.2891 +	elfSectionHeaders = sh;
  1.2892 +	elfSectionHeadersStringTable = stringTable;
  1.2893 +	elfSectionHeadersCount       = count;
  1.2894 +
  1.2895 +	for (i = 0; i < count; i++)
  1.2896 +	{
  1.2897 +		//    printf("SH %d %-20s %08x %08x %08x %08x %08x %08x %08x %08x\n",
  1.2898 +		//   i, &stringTable[sh[i]->name], sh[i]->name, sh[i]->type,
  1.2899 +		//   sh[i]->flags, sh[i]->addr, sh[i]->offset, sh[i]->size,
  1.2900 +		//   sh[i]->link, sh[i]->info);
  1.2901 +		if (READ32LE(&sh[i]->flags) & 2) // load section
  1.2902 +		{
  1.2903 +			if (cpuIsMultiBoot)
  1.2904 +			{
  1.2905 +				if (READ32LE(&sh[i]->addr) >= 0x2000000 &&
  1.2906 +				    READ32LE(&sh[i]->addr) <= 0x203ffff)
  1.2907 +				{
  1.2908 +					memcpy(&workRAM[READ32LE(&sh[i]->addr) & 0x3ffff], data +
  1.2909 +					       READ32LE(&sh[i]->offset),
  1.2910 +					       READ32LE(&sh[i]->size));
  1.2911 +				}
  1.2912 +			}
  1.2913 +			else
  1.2914 +			{
  1.2915 +				if (READ32LE(&sh[i]->addr) >= 0x8000000 &&
  1.2916 +				    READ32LE(&sh[i]->addr) <= 0x9ffffff)
  1.2917 +				{
  1.2918 +					memcpy(&rom[READ32LE(&sh[i]->addr) & 0x1ffffff],
  1.2919 +					       data + READ32LE(&sh[i]->offset),
  1.2920 +					       READ32LE(&sh[i]->size));
  1.2921 +					size += READ32LE(&sh[i]->size);
  1.2922 +				}
  1.2923 +			}
  1.2924 +		}
  1.2925 +	}
  1.2926 +
  1.2927 +	if (parseDebug)
  1.2928 +	{
  1.2929 +		fprintf(stderr, "Parsing debug info\n");
  1.2930 +
  1.2931 +		ELFSectionHeader *dbgHeader = elfGetSectionByName(".debug_info");
  1.2932 +		if (dbgHeader == NULL)
  1.2933 +		{
  1.2934 +			fprintf(stderr, "Cannot find debug information\n");
  1.2935 +			goto end;
  1.2936 +		}
  1.2937 +
  1.2938 +		ELFSectionHeader *h = elfGetSectionByName(".debug_abbrev");
  1.2939 +		if (h == NULL)
  1.2940 +		{
  1.2941 +			fprintf(stderr, "Cannot find abbreviation table\n");
  1.2942 +			goto end;
  1.2943 +		}
  1.2944 +
  1.2945 +		elfDebugInfo = (DebugInfo *)calloc(sizeof(DebugInfo), 1);
  1.2946 +		u8 *abbrevdata = elfReadSection(data, h);
  1.2947 +
  1.2948 +		h = elfGetSectionByName(".debug_str");
  1.2949 +
  1.2950 +		if (h == NULL)
  1.2951 +			elfDebugStrings = NULL;
  1.2952 +		else
  1.2953 +			elfDebugStrings = (char *)elfReadSection(data, h);
  1.2954 +
  1.2955 +		u8 *debugdata = elfReadSection(data, dbgHeader);
  1.2956 +
  1.2957 +		elfDebugInfo->debugdata = data;
  1.2958 +		elfDebugInfo->infodata  = debugdata;
  1.2959 +
  1.2960 +		u32 total = READ32LE(&dbgHeader->size);
  1.2961 +		u8 *end   = debugdata + total;
  1.2962 +		u8 *ddata = debugdata;
  1.2963 +
  1.2964 +		CompileUnit *last = NULL;
  1.2965 +		CompileUnit *unit = NULL;
  1.2966 +
  1.2967 +		while (ddata < end)
  1.2968 +		{
  1.2969 +			unit         = elfParseCompUnit(ddata, abbrevdata);
  1.2970 +			unit->offset = ddata-debugdata;
  1.2971 +			elfParseLineInfo(unit, data);
  1.2972 +			if (last == NULL)
  1.2973 +				elfCompileUnits = unit;
  1.2974 +			else
  1.2975 +				last->next = unit;
  1.2976 +			last   = unit;
  1.2977 +			ddata += 4 + unit->length;
  1.2978 +		}
  1.2979 +		elfParseAranges(data);
  1.2980 +		CompileUnit *comp = elfCompileUnits;
  1.2981 +		while (comp)
  1.2982 +		{
  1.2983 +			ARanges *r = elfDebugInfo->ranges;
  1.2984 +			for (int i = 0; i < elfDebugInfo->numRanges; i++)
  1.2985 +				if (r[i].offset == comp->offset)
  1.2986 +				{
  1.2987 +					comp->ranges = &r[i];
  1.2988 +					break;
  1.2989 +				}
  1.2990 +			comp = comp->next;
  1.2991 +		}
  1.2992 +		elfParseCFA(data);
  1.2993 +		elfReadSymtab(data);
  1.2994 +	}
  1.2995 +end:
  1.2996 +	if (sh)
  1.2997 +	{
  1.2998 +		free(sh);
  1.2999 +	}
  1.3000 +
  1.3001 +	elfSectionHeaders = NULL;
  1.3002 +	elfSectionHeadersStringTable = NULL;
  1.3003 +	elfSectionHeadersCount       = 0;
  1.3004 +
  1.3005 +	return true;
  1.3006 +}
  1.3007 +
  1.3008 +extern bool8 parseDebug;
  1.3009 +
  1.3010 +bool elfRead(const char *name, int& siz, FILE *f)
  1.3011 +{
  1.3012 +	fseek(f, 0, SEEK_END);
  1.3013 +	long size = ftell(f);
  1.3014 +	elfFileData = (u8 *)malloc(size);
  1.3015 +	fseek(f, 0, SEEK_SET);
  1.3016 +	fread(elfFileData, 1, size, f);
  1.3017 +	fclose(f);
  1.3018 +
  1.3019 +	ELFHeader *header = (ELFHeader *)elfFileData;
  1.3020 +
  1.3021 +	if (READ32LE(&header->magic) != 0x464C457F ||
  1.3022 +	    READ16LE(&header->e_machine) != 40 ||
  1.3023 +	    header->clazz != 1)
  1.3024 +	{
  1.3025 +		systemMessage(0, N_("Not a valid ELF file %s"), name);
  1.3026 +		free(elfFileData);
  1.3027 +		elfFileData = NULL;
  1.3028 +		return false;
  1.3029 +	}
  1.3030 +
  1.3031 +	if (!elfReadProgram(header, elfFileData, siz, parseDebug))
  1.3032 +	{
  1.3033 +		free(elfFileData);
  1.3034 +		elfFileData = NULL;
  1.3035 +		return false;
  1.3036 +	}
  1.3037 +
  1.3038 +	return true;
  1.3039 +}
  1.3040 +
  1.3041 +void elfCleanUp(Object *o)
  1.3042 +{
  1.3043 +	free(o->location);
  1.3044 +}
  1.3045 +
  1.3046 +void elfCleanUp(Function *func)
  1.3047 +{
  1.3048 +	Object *o = func->parameters;
  1.3049 +	while (o)
  1.3050 +	{
  1.3051 +		elfCleanUp(o);
  1.3052 +		Object *next = o->next;
  1.3053 +		free(o);
  1.3054 +		o = next;
  1.3055 +	}
  1.3056 +
  1.3057 +	o = func->variables;
  1.3058 +	while (o)
  1.3059 +	{
  1.3060 +		elfCleanUp(o);
  1.3061 +		Object *next = o->next;
  1.3062 +		free(o);
  1.3063 +		o = next;
  1.3064 +	}
  1.3065 +	free(func->frameBase);
  1.3066 +}
  1.3067 +
  1.3068 +void elfCleanUp(ELFAbbrev **abbrevs)
  1.3069 +{
  1.3070 +	for (int i = 0; i < 121; i++)
  1.3071 +	{
  1.3072 +		ELFAbbrev *abbrev = abbrevs[i];
  1.3073 +
  1.3074 +		while (abbrev)
  1.3075 +		{
  1.3076 +			free(abbrev->attrs);
  1.3077 +			ELFAbbrev *next = abbrev->next;
  1.3078 +			free(abbrev);
  1.3079 +
  1.3080 +			abbrev = next;
  1.3081 +		}
  1.3082 +	}
  1.3083 +}
  1.3084 +
  1.3085 +void elfCleanUp(Type *t)
  1.3086 +{
  1.3087 +	switch (t->type)
  1.3088 +	{
  1.3089 +	case TYPE_function:
  1.3090 +		if (t->function)
  1.3091 +		{
  1.3092 +			Object *o = t->function->args;
  1.3093 +			while (o)
  1.3094 +			{
  1.3095 +				elfCleanUp(o);
  1.3096 +				Object *next = o->next;
  1.3097 +				free(o);
  1.3098 +				o = next;
  1.3099 +			}
  1.3100 +			free(t->function);
  1.3101 +		}
  1.3102 +		break;
  1.3103 +	case TYPE_array:
  1.3104 +		if (t->array)
  1.3105 +		{
  1.3106 +			free(t->array->bounds);
  1.3107 +			free(t->array);
  1.3108 +		}
  1.3109 +		break;
  1.3110 +	case TYPE_struct:
  1.3111 +	case TYPE_union:
  1.3112 +		if (t->structure)
  1.3113 +		{
  1.3114 +			for (int i = 0; i < t->structure->memberCount; i++)
  1.3115 +			{
  1.3116 +				free(t->structure->members[i].location);
  1.3117 +			}
  1.3118 +			free(t->structure->members);
  1.3119 +			free(t->structure);
  1.3120 +		}
  1.3121 +		break;
  1.3122 +	case TYPE_enum:
  1.3123 +		if (t->enumeration)
  1.3124 +		{
  1.3125 +			free(t->enumeration->members);
  1.3126 +			free(t->enumeration);
  1.3127 +		}
  1.3128 +		break;
  1.3129 +	case TYPE_base:
  1.3130 +	case TYPE_pointer:
  1.3131 +	case TYPE_void:
  1.3132 +	case TYPE_reference:
  1.3133 +		break; // nothing to do
  1.3134 +	}
  1.3135 +}
  1.3136 +
  1.3137 +void elfCleanUp(CompileUnit *comp)
  1.3138 +{
  1.3139 +	elfCleanUp(comp->abbrevs);
  1.3140 +	free(comp->abbrevs);
  1.3141 +	Function *func = comp->functions;
  1.3142 +	while (func)
  1.3143 +	{
  1.3144 +		elfCleanUp(func);
  1.3145 +		Function *next = func->next;
  1.3146 +		free(func);
  1.3147 +		func = next;
  1.3148 +	}
  1.3149 +	Type *t = comp->types;
  1.3150 +	while (t)
  1.3151 +	{
  1.3152 +		elfCleanUp(t);
  1.3153 +		Type *next = t->next;
  1.3154 +		free(t);
  1.3155 +		t = next;
  1.3156 +	}
  1.3157 +	Object *o = comp->variables;
  1.3158 +	while (o)
  1.3159 +	{
  1.3160 +		elfCleanUp(o);
  1.3161 +		Object *next = o->next;
  1.3162 +		free(o);
  1.3163 +		o = next;
  1.3164 +	}
  1.3165 +	if (comp->lineInfoTable)
  1.3166 +	{
  1.3167 +		free(comp->lineInfoTable->lines);
  1.3168 +		free(comp->lineInfoTable->files);
  1.3169 +		free(comp->lineInfoTable);
  1.3170 +	}
  1.3171 +}
  1.3172 +
  1.3173 +void elfCleanUp()
  1.3174 +{
  1.3175 +	CompileUnit *comp = elfCompileUnits;
  1.3176 +
  1.3177 +	while (comp)
  1.3178 +	{
  1.3179 +		elfCleanUp(comp);
  1.3180 +		CompileUnit *next = comp->next;
  1.3181 +		free(comp);
  1.3182 +		comp = next;
  1.3183 +	}
  1.3184 +	elfCompileUnits = NULL;
  1.3185 +	free(elfSymbols);
  1.3186 +	elfSymbols = NULL;
  1.3187 +	//  free(elfSymbolsStrTab);
  1.3188 +	elfSymbolsStrTab = NULL;
  1.3189 +
  1.3190 +	elfDebugStrings = NULL;
  1.3191 +	if (elfDebugInfo)
  1.3192 +	{
  1.3193 +		int num = elfDebugInfo->numRanges;
  1.3194 +		int i;
  1.3195 +		for (i = 0; i < num; i++)
  1.3196 +		{
  1.3197 +			free(elfDebugInfo->ranges[i].ranges);
  1.3198 +		}
  1.3199 +		free(elfDebugInfo->ranges);
  1.3200 +		free(elfDebugInfo);
  1.3201 +		elfDebugInfo = NULL;
  1.3202 +	}
  1.3203 +
  1.3204 +	if (elfFdes)
  1.3205 +	{
  1.3206 +		if (elfFdeCount)
  1.3207 +		{
  1.3208 +			for (int i = 0; i < elfFdeCount; i++)
  1.3209 +				free(elfFdes[i]);
  1.3210 +		}
  1.3211 +		free(elfFdes);
  1.3212 +
  1.3213 +		elfFdes     = NULL;
  1.3214 +		elfFdeCount = 0;
  1.3215 +	}
  1.3216 +
  1.3217 +	ELFcie *cie = elfCies;
  1.3218 +	while (cie)
  1.3219 +	{
  1.3220 +		ELFcie *next = cie->next;
  1.3221 +		free(cie);
  1.3222 +		cie = next;
  1.3223 +	}
  1.3224 +	elfCies = NULL;
  1.3225 +
  1.3226 +	if (elfFileData)
  1.3227 +	{
  1.3228 +		free(elfFileData);
  1.3229 +		elfFileData = NULL;
  1.3230 +	}
  1.3231 +}
  1.3232 +