disasm: support block disassembly (eg 80000000:4k).
This commit is contained in:
parent
c5a7071dcc
commit
3f462a2d07
16
README.md
16
README.md
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue