disasm: support block disassembly (eg 80000000:4k).

This commit is contained in:
Lephenixnoir 2020-02-28 16:42:46 +01:00
parent c5a7071dcc
commit 3f462a2d07
3 changed files with 41 additions and 16 deletions

0
Makefile Normal file → Executable file
View File

View File

@ -41,9 +41,11 @@ instruction tables to lists of named syscalls. These resources are usually
public for the most part, but some of the reverse-engineering results of the
community are kept private.
A set of base files for a working library can be found [on my section of the
Planète Casio bible](https://bible.planet-casio.com/lephenixnoir/fxos-library/).
You can use your own files, but you probably want the assembler tables anyway.
A set of base files for a working library can be found in the
[`base-library` folder](base-library) of this repository,
which includes a suitable configuration file. Though unless you want to redo
the research by yourself, you can get shared community data from the
[fxdoc repository](/Lephenixnoir/fxdoc).
Next, fxos should be told where to find these files. A small configuration file
should be added at `$HOME/.config/fxos/config` to do this. The configuration
@ -56,14 +58,14 @@ With the default library, the configuration file should look like this:
```
library: /path/to/fxos-library
load: /path/to/fxos-library/asm
load: /path/to/fxos-library/asmtables
load: /path/to/fxos-library/targets
load: /path/to/fxos-library/symbols
```
This means that fxos data files will be automatically loaded at startup from
the `asm`, `targets` and `symbols` directories. Targets refer to OS files and
RAM dumps by path, and these paths will be interpreted relatively to the
the `asmtables`, `targets` and `symbols` directories. Targets refer to OS files
and RAM dumps by path, and these paths will be interpreted relatively to the
`fxos-library` folder. If you create `$PREFIX/share/fxos`, it will also be used
as if mentioned on a `library:` line.
@ -216,8 +218,6 @@ Some of the advertised interface is not yet implemented:
object to understand what it is used for. An example would be: given a 32-bit
value, find all places in the code where it is loaded from memory, and match
these places with the known OS structure to see what kind of code uses it.
* The location specified `<address>:<len>` is not supported right now, though I
don't know how long I'll last without it.
## Reporting issues and results

View File

@ -18,17 +18,19 @@ int disassembly(Library &library, Target &target, char const *ref,
std::vector<std::string> passes)
{
Disassembly disasm(target);
int len=0;
/* Observe the target only if it has an OS mapped */
std::unique_ptr<OS> os;
if(target.covers(MemoryRegion::ROM))
os = std::make_unique<OS>(target);
if(target.covers(MemoryRegion::ROM)) os = std::make_unique<OS>(target);
uint32_t address;
/* Parameters inside the ref */
uint32_t address = -1;
uint32_t blocklen;
int syscall_id;
int len = 0;
char blockmul[2] = { 0 };
enum { RefNone=0, RefSyscall, RefAddress } reftype = RefNone;
enum { RefNone=0, RefSyscall, RefAddress, RefBlock } reftype = RefNone;
/* Parse different flavors of references. %<hexa>: syscall */
if(sscanf(ref, "%%%x", &syscall_id) == 1)
@ -36,6 +38,21 @@ int disassembly(Library &library, Target &target, char const *ref,
/* Pure hexa: address */
else if(sscanf(ref, "%x%n", &address, &len) == 1 && !ref[len])
reftype = RefAddress;
/* Hexa with a size: a block */
else if(sscanf(ref,"%x:%x%n",&address,&blocklen,&len)==2 && !ref[len])
reftype = RefBlock;
/* Variant of block size that includes a letter k/M/G (note that the
"%[]" specifier never matches empty strings */
else if(sscanf(ref, "%x:%x%1[kMG]%n", &address, &blocklen, blockmul,
&len) == 3 && !ref[len])
{
reftype = RefBlock;
int mul = blockmul[0];
if(mul == 'k') blocklen <<= 10;
if(mul == 'M') blocklen <<= 20;
if(mul == 'G') blocklen <<= 30;
}
/* Anything else: look up symbols */
else
{
@ -71,7 +88,7 @@ int disassembly(Library &library, Target &target, char const *ref,
address = os->syscall(syscall_id);
}
else if(reftype == RefAddress)
if(reftype == RefAddress || reftype == RefBlock)
{
if(address & 1)
{
@ -80,7 +97,15 @@ int disassembly(Library &library, Target &target, char const *ref,
address++;
}
}
else
if(reftype == RefBlock)
{
/* Load the block into memory */
for(uint32_t pc = address; pc < address + blocklen; pc += 2)
{
disasm.readins(pc);
}
}
if(reftype == RefNone)
{
log(ERR "cannot interpret '%s' (not a syscall id, not an "
"address, and no such symbol in library)", ref);
@ -92,7 +117,7 @@ int disassembly(Library &library, Target &target, char const *ref,
auto start = timer_start();
log(LOG "Running pass %s...\\", pass);
if(pass == "cfg")
if(pass == "cfg" && reftype != RefBlock)
{
CfgPass p(disasm);
p.run(address);