mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00

- PicoDrive was originally released by fDave with simple "free for non-commercial use / For commercial use, separate licencing terms must be obtained" license and I kept it in my releases. - in 2011, fDave re-released his code (same that I used as base many years ago) dual licensed with GPLv2 and MAME licenses: https://code.google.com/p/cyclone68000/ Based on the above I now proclaim that the whole source code is licensed under the MAME license as more elaborate form of "for non-commercial use". If that raises any doubt, I announce that all my modifications (which is the vast majority of code by now) is licensed under the MAME license, as it reads in COPYING file in this commit. This does not affect ym2612.c/sn76496.c that were MAME licensed already from the beginning.
232 lines
5 KiB
C
232 lines
5 KiB
C
/*
|
|
* PicoDrive
|
|
* (C) notaz, 2009,2010
|
|
*
|
|
* This work is licensed under the terms of MAME license.
|
|
* See COPYING file in the top-level directory.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <bfd.h>
|
|
#include <dis-asm.h>
|
|
|
|
#include "host_dasm.h"
|
|
|
|
extern char **g_argv;
|
|
|
|
static struct disassemble_info di;
|
|
|
|
#ifdef ARM
|
|
#define print_insn_func print_insn_little_arm
|
|
#define BFD_ARCH bfd_arch_arm
|
|
#define BFD_MACH bfd_mach_arm_4T
|
|
#else
|
|
#define print_insn_func print_insn_i386_intel
|
|
#define BFD_ARCH bfd_arch_i386
|
|
#define BFD_MACH bfd_mach_i386_i386_intel_syntax
|
|
#endif
|
|
|
|
/* symbols */
|
|
static asymbol **symbols;
|
|
static long symcount, symstorage;
|
|
static int init_done;
|
|
|
|
/* Filter out (in place) symbols that are useless for disassembly.
|
|
COUNT is the number of elements in SYMBOLS.
|
|
Return the number of useful symbols. */
|
|
static long
|
|
remove_useless_symbols (asymbol **symbols, long count)
|
|
{
|
|
asymbol **in_ptr = symbols, **out_ptr = symbols;
|
|
|
|
while (--count >= 0)
|
|
{
|
|
asymbol *sym = *in_ptr++;
|
|
|
|
if (sym->name == NULL || sym->name[0] == '\0' || sym->name[0] == '$')
|
|
continue;
|
|
if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM))
|
|
continue;
|
|
if (bfd_is_und_section (sym->section)
|
|
|| bfd_is_com_section (sym->section))
|
|
continue;
|
|
if (sym->value + sym->section->vma == 0)
|
|
continue;
|
|
/*
|
|
printf("sym: %08lx %04x %08x v %08x \"%s\"\n",
|
|
(unsigned int)sym->value, (unsigned int)sym->flags, (unsigned int)sym->udata.i,
|
|
(unsigned int)sym->section->vma, sym->name);
|
|
*/
|
|
*out_ptr++ = sym;
|
|
}
|
|
|
|
return out_ptr - symbols;
|
|
}
|
|
|
|
static void slurp_symtab(const char *filename)
|
|
{
|
|
bfd *abfd;
|
|
|
|
symcount = 0;
|
|
|
|
abfd = bfd_openr(filename, NULL);
|
|
if (abfd == NULL) {
|
|
fprintf(stderr, "failed to open: %s\n", filename);
|
|
goto no_symbols;
|
|
}
|
|
|
|
if (!bfd_check_format(abfd, bfd_object))
|
|
goto no_symbols;
|
|
|
|
if (!(bfd_get_file_flags(abfd) & HAS_SYMS))
|
|
goto no_symbols;
|
|
|
|
symstorage = bfd_get_symtab_upper_bound(abfd);
|
|
if (symstorage <= 0)
|
|
goto no_symbols;
|
|
|
|
symbols = malloc(symstorage);
|
|
if (symbols == NULL)
|
|
goto no_symbols;
|
|
|
|
symcount = bfd_canonicalize_symtab(abfd, symbols);
|
|
if (symcount < 0)
|
|
goto no_symbols;
|
|
|
|
symcount = remove_useless_symbols(symbols, symcount);
|
|
// bfd_close(abfd);
|
|
return;
|
|
|
|
no_symbols:
|
|
fprintf(stderr, "no symbols in %s\n", bfd_get_filename(abfd));
|
|
if (symbols != NULL)
|
|
free(symbols);
|
|
symbols = NULL;
|
|
if (abfd != NULL)
|
|
bfd_close(abfd);
|
|
}
|
|
|
|
static const char *lookup_name(bfd_vma addr)
|
|
{
|
|
asymbol **sptr = symbols;
|
|
int i;
|
|
|
|
for (i = 0; i < symcount; i++) {
|
|
asymbol *sym = *sptr++;
|
|
|
|
if (addr == sym->value + sym->section->vma)
|
|
return sym->name;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* Like target_read_memory, but slightly different parameters. */
|
|
static int
|
|
dis_asm_read_memory(bfd_vma memaddr, bfd_byte *myaddr, unsigned int len,
|
|
struct disassemble_info *info)
|
|
{
|
|
memcpy(myaddr, (void *)(int)memaddr, len);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
dis_asm_memory_error(int status, bfd_vma memaddr,
|
|
struct disassemble_info *info)
|
|
{
|
|
fprintf(stderr, "memory_error %p\n", (void *)(int)memaddr);
|
|
}
|
|
|
|
static void
|
|
dis_asm_print_address(bfd_vma addr, struct disassemble_info *info)
|
|
{
|
|
const char *name;
|
|
|
|
printf("%08x", (int)addr);
|
|
|
|
name = lookup_name(addr);
|
|
if (name != NULL)
|
|
printf(" <%s>", name);
|
|
}
|
|
|
|
static int insn_printf(void *f, const char *format, ...)
|
|
{
|
|
va_list args;
|
|
size_t n;
|
|
|
|
va_start(args, format);
|
|
n = vprintf(format, args);
|
|
va_end(args);
|
|
|
|
return n;
|
|
}
|
|
|
|
static void host_dasm_init(void)
|
|
{
|
|
bfd_init();
|
|
slurp_symtab(g_argv[0]);
|
|
|
|
init_disassemble_info(&di, NULL, insn_printf);
|
|
di.flavour = bfd_target_unknown_flavour;
|
|
di.memory_error_func = dis_asm_memory_error;
|
|
di.print_address_func = dis_asm_print_address;
|
|
// di.symbol_at_address_func = dis_asm_symbol_at_address;
|
|
di.read_memory_func = dis_asm_read_memory;
|
|
di.arch = BFD_ARCH;
|
|
di.mach = BFD_MACH;
|
|
di.endian = BFD_ENDIAN_LITTLE;
|
|
disassemble_init_for_target(&di);
|
|
init_done = 1;
|
|
}
|
|
|
|
void host_dasm(void *addr, int len)
|
|
{
|
|
bfd_vma vma_end, vma = (bfd_vma)(long)addr;
|
|
const char *name;
|
|
|
|
if (!init_done)
|
|
host_dasm_init();
|
|
|
|
vma_end = vma + len;
|
|
while (vma < vma_end) {
|
|
name = lookup_name(vma);
|
|
if (name != NULL)
|
|
printf("%s:\n", name);
|
|
|
|
printf(" %08lx ", (long)vma);
|
|
vma += print_insn_func(vma, &di);
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
void host_dasm_new_symbol_(void *addr, const char *name)
|
|
{
|
|
bfd_vma vma = (bfd_vma)(long)addr;
|
|
asymbol *sym, **tmp;
|
|
|
|
if (!init_done)
|
|
host_dasm_init();
|
|
if (symbols == NULL)
|
|
return;
|
|
if (symstorage <= symcount * sizeof(symbols[0])) {
|
|
tmp = realloc(symbols, symstorage * 2);
|
|
if (tmp == NULL)
|
|
return;
|
|
symstorage *= 2;
|
|
symbols = tmp;
|
|
}
|
|
|
|
symbols[symcount] = calloc(sizeof(*symbols[0]), 1);
|
|
if (symbols[symcount] == NULL)
|
|
return;
|
|
|
|
// a HACK (should use correct section), but ohwell
|
|
sym = symbols[symcount];
|
|
sym->section = symbols[0]->section;
|
|
sym->value = vma - sym->section->vma;
|
|
sym->name = name;
|
|
symcount++;
|
|
}
|
|
|