view leo-obj/tool/ln.c @ 392:35009c936a4a

compal/melody-extr: first attempt at actual melody extraction
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 01 Apr 2022 06:03:47 +0000
parents 71e25510f5af
children
line wrap: on
line source

/*
 * Making use of line number records
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include "filestruct.h"
#include "intstruct.h"
#include "coffconst.h"
#include "globals.h"

extern unsigned get_u16(), get_u32();

cmd_ln()
{
	unsigned n, m;
	struct internal_scnhdr *sec;
	u_char *rec;

	get_int_section_table();
	for (n = 0; n < nsections; n++) {
		sec = sections + n;
		if (!sec->nlineent)
			continue;
		printf("%s:\n\n", sec->name);
		rec = filemap + sec->line_offset;
		for (m = 0; m < sec->nlineent; m++, rec += 6)
			printf("%08X  %04X\n", get_u32(rec), get_u16(rec + 4));
		putchar('\n');
	}
	exit(0);
}

static unsigned
get_lineno_base(func_symidx)
	unsigned func_symidx;
{
	struct internal_syment *func_sym, *bf_sym;

	if (func_symidx >= nsymtab)
		return 0;
	func_sym = symtab[func_symidx];
	if (!func_sym->aux)
		return 0;
	if (func_symidx + 2 >= nsymtab)
		return 0;
	bf_sym = symtab[func_symidx + 2];
	if (!bf_sym->aux)
		return 0;
	return get_u16(bf_sym->aux + 4);
}

get_lineno_array(sec, arr_rtn, count_rtn, actual_numbers)
	struct internal_scnhdr *sec;
	struct internal_lineno **arr_rtn;
	unsigned *count_rtn;
{
	struct internal_lineno *array;
	unsigned cur, last;
	unsigned n, m;
	unsigned base, incr;
	u_char *rec;

	array = malloc(sizeof(struct internal_lineno) * sec->nlineent);
	if (!array) {
		perror("malloc");
		exit(1);
	}
	m = 0;
	rec = filemap + sec->line_offset;
	base = 0;
	for (n = 0; n < sec->nlineent; n++, rec += 6) {
		incr = get_u16(rec + 4);
		if (!incr) {
			if (actual_numbers)
				base = get_lineno_base(get_u32(rec));
			continue;
		}
		cur = get_u32(rec);
		if (m) {
			if (cur < last) {
				fprintf(stderr,
		"error: line # addresses in section %s going backward\n",
					sec->name);
				exit(1);
			}
			if (cur == last && !actual_numbers)
				continue;
		}
		if (actual_numbers) {
			if (!base) {
				fprintf(stderr,
					"error: no line # base in section %s\n",
					sec->name);
				exit(1);
			}
			array[m].lineno = base + incr - 1;
		}
		array[m++].location = cur;
		last = cur;
	}
	*arr_rtn = array;
	*count_rtn = m;
}