5

In the firmwares I met the situation when some register value is set at startup, and then it's implicitly used as a base address to access the variables.

e.g. register r13 is set to 0x40000000 which is address of RAM. And then all over the code the variables are being accessed as offset to r13. Hex Rays doesn't like it at all, and generates lots of red variables for which VALUE MAY BE UNDEFINED

Is there any way to set the register value, so that Hex Rays uses it in every function?

EDIT: Actually IDA does it in some cases. PowerPC processor module seems to know about __init_registers() function when working with ELF files and uses r13 value to calculate the global variables offsets relative to r13. enter image description here

And I've learned that it actually creates User defined offsets in such cases.

enter image description here

But still don't know how it's implemented to know r13 value.

2 Answers 2

2

I don't know off the top of my head if there's an option you can set for that, but that's the type of thing that's utterly trivial to write a Hex-Rays plugin for. I bet that would be less than 25 lines of code. If you can send a link to a binary, I'll write a script to demonstrate. Assuming you're writing IDAPython (the details would only be slightly different in C++), the outline would be:

  1. Derive a class from mop_visitor_t, whose visit_mop method: requires is_target to be false; compares the operand against mop_r; if so, compares the .r union element against the microregister number for r13. If found, replace the operand with your constant (i.e. call mop_t::make_number(0x40000000) on the operand).
  2. Derive a class named R13ReplaceHooks off of ida_hexrays.Hexrays_Hooks.
  3. Override its microcode method to call mba_t::for_all_ops with an instance of the visitor above.
  4. At the bottom of the script, a bit of glue code to allow easy installation and removal of the hook, as in:
try:
    r13replacehooks.unhook()
    del r13replacehooks
except NameError as e:
    pass
finally:
    r13replacehooks = R13ReplaceHooks()
    r13replacehooks.hook()
  1. That's it.

===== EDIT TO ADD =====

After writing the answer above, I had some further thoughts on the matter.

Red/orange variables and warnings about values being undefined is not what I would expect in this situation. Rather, I would expect that you would see a bunch of __usercall prototypes that had r13 as an argument, and then you would see nasty pointer arithmetic typical of code that needs a structure definition, as in *(QWORD *)((QWORD)x + 20). So I guess an alternative answer would be that you could add those arguments to the function prototypes, declare one big structure for the data section in question, and define the r13 __usercall arguments as being pointers to that structure.

I tend to think that the other answer would be generally easier to work with, but this approach does have one upside: you can use Hex-Rays' "Jump to xref globally" feature to track cross-references to the data members. This won't be the case for the register replacement approach in the other answer, since the references aren't really there in the code; in the other approach, those references will be created on the fly, and not stored in the database in a form that can be browsed through the normal cross-reference machinery. In this approach, the references will be available persistently via the structure cross-references.

0

Since r13 is a memory mapped register, you should create a new RAM segment and define all of your registers there on the correct virtual addresses (use ida_bytes.create_data() and idc.set_name()). You can then use it in the code as a reference and it would be resolved everywhere.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.