Index of /~plonka/loadimm

[ICO]NameLast modifiedSizeDescription

[PARENTDIR]Parent Directory  -  
[   ]loadimm2000-03-03 16:26 15K 

loadimm - a utility to examine or modify SPARC "load immediate" instructions in ELF 32-bit SPARC executables

NAME

loadimm - a utility to examine or modify SPARC ``load immediate'' instructions in ELF 32-bit SPARC executables


SYNOPSIS

 loadimm [-Vv] [-e] [-x] [-a] [ <-n new_value | -i inc_value> ] <constant> <executable> ...


DESCRIPTION

This utility is used to examine or modify the ``load immediate'' instructions in ELF 32-bit SPARC executables. These instructions are those which load ``hard-coded'' 32-bit constant values into registers.

As-is, this utility will probably only be of use under Solaris on a 32-bit SPARC machine because (a) the ``elfprint'' utility it uses is based on the source found in Solaris' elf(3E) man page, (b) ``elfprint'' requires libelf(4) to link, and (c) it invokes adb(1), expecting it work exactly like Solaris' adb(1) command.

The options and arguments are:

-v
be verbose with messages (mnemonic: 'v'erbose)

-e
just print the source to the ``elfprint'' utility to standard output. (This is for redirecting to ``elfprint.c''.) This utility is used to determine the attributes of the executables' text segments. (``elfprint'' must be compiled installed in the user's PATH before ``loadimm'' is fully functional.) mnemonic: 'e'lfprint

-x
show addresses in hex (mnemonic: he'x')

-a
invoke adb(1). If -n or -i is specified, adb(1) will be invoked in write mode (i.e. adb -w) and will modify the executable(s). (mnemonic: invoke 'a'db)

-n new_value
change constant to this new value. This value can be specified in decimal or hexadecimal (with ``0x'' prefix). (mnemonic: 'n'ew value)

-i inc_value
increment constant by this value (mnemonic: 'i'ncrement)

constant
The constant value to be found or changed (if -n or -i is used). This value can be specified in decimal or hex (with ``0x'' prefix).

executable
The name of the 32-bit SPARC ELF executable to be scanned or modified (if -n or -i is used).

On the SPARC, as with many (most, all?) RISC processors, it generally takes more than one instruction to load a long word constant into a register. This is most commonly done, for example, like this:

  sethi %hi(val), %r17
  or    %r17, %lo(val), %r17

or like this:

  sethi %hi(val), %r17
  add   %r17, %lo(val), %r17

So, if we can determine the file offset and size of the text segment within the executable, it is a simple matter of programming to modify those instructions to load a different value. This is useful in executables for which one doesn't have the source code but would like to change some hard- coded ``magic numbers'' within the executable. For instance, one can change a hard-coded TCP port number to which a given executable bind(2)s and listen(2)s.

This utility works by:

  1. using an external command called ``elfprint''. The ``elfprint'' used here is a slightly modified version of the example.c in the Solaris 2.6 elf(3E) man page. It acts like the ``elfprint'' command demonstrated there, but also prints the file offset, size, and address of each segment. (Invoke this utility with the -e option to generate the ``elfprint'' source, then make and install that executable in the PATH.)

  2. scanning the text segment for what look like ``load immediate'' instructions, i.e. SETHI followed by OR or sethi followed by AND. (Precalculated bitmasks are used to identify these instructions, rather than trying to dis(1)assemble/decompile the executables which would be prohibitively time consuming. strtoul was *very* useful here.)

  3. optionally invoking adb(1) to patch those instruction pairs within the executable. (If the -a option is not specified, it just shows you the adb(1) commands that would perform the change.)


CAVEATS

This is a brute force approach to modifying the executable without trying to understand the context in which the instructions occur. As such it could do bad things - specifically, it could modify all the occurences of instructions that load the given constant, rather than just the ones sufficient to effect the change that you intended. If in doubt, don't use -i or -n with -a!, instead just do, for example:

   $ loadimm 0xd00d my_executable

and then invoke adb manually. As you invoke the ``suggested'' adb command, carefully consider the context in which the target instructions (which are displayed with the ?i adb commands) occur before issuing the ?W adb instructions (which actually perform the modifications.) Of course, always save a backup of your executable and the file systems containing the files/databases on which it operates in the event that something goes terribly wrong.

Also, if you modify an executable authored by someone else (which is presumably what you're doing since you don't have source code), *don't* report a bug that has only been observed in the modified executable. (Once the executable has been modified - essentially all warranties/ guarantees are void.) Go back to the original, and reproduce the bug there before calling for support.

Before doing an update, it would be a good idea to scan your executable to be sure it doesn't already contain other references to your new constant's value, so that you can be sure that, in the future, it would be possible to locate the modified instructions in case you want to undo what's been done.


EXAMPLE

If you'd like an executable to bind port 0xbabe rather than 0xd00d, follow these steps:

First, if you haven't already done so, build the ``elfprint'' utility (Note that this utility differs slightly from the ``elfprint'' that is shown in the Solaris elf(3E) man page):

   $ loadimm -e > elfprint.c
   $ chmod +x elfprint.c
   $ ./elfprint.c # yes, actually execute the source file (as a shell script)!
   gcc -o ./elfprint ./elfprint.c -lelf
   $ # if necessary, install "elfprint" so that it is in your PATH

Check that a ``load immediate 0xbabe'' instruction doesn't already exist in the executable:

   $ loadimm -v 0xbabe my_executable

If no occurences are found, do the modification:

   $ loadimm -n 0xbabe 0xd00d my_executable

If ever necessary, revert to original:

   $ loadimm -n 0xd00d 0xbabe my_executable


SEE ALSO

elf, libelf, adb


COPYRIGHT

Copyright 1999-2000 Dave Plonka.


AUTHOR

Dave Plonka