Your string seems to have an xref (cross reference, see below) from 0040C624
. This string might just be an entry in an array of error strings, with the array itself beginning just a little before 0040C624
. Your original source code may have looked like this:
char *unused="unused string";
char *errors[] = {
"error 0",
"some other error",
"yet another error",
"Erase error!",
"....",
};
void print_error_message(int index) {
puts(errors[index]);
}
int handle_erase_error() {
print_error_message(3);
}
If you compile this (i used gnu C on linux, gcc -m32 xref.c
) and load the object code into IDA, it becomes (irrelevant parts omitted):
.text:08000000 print_error_message proc near ; CODE XREF: handle_erase_error+Dp
.text:08000000 push ebp
.text:08000001 mov ebp, esp
.text:08000003 sub esp, 18h
.text:08000006 mov eax, [ebp+8]
.text:08000009 mov eax, errors[eax*4]
.text:08000010 mov [esp], eax ; s
.text:08000013 call puts
.text:08000018 leave
.text:08000019 retn
.text:08000019 print_error_message endp
.data:08000030 unused dd offset aUnusedString ; "unused string"
.data:08000034 errors dd offset aError0 ; DATA XREF: print_error_message+9r
.data:08000034 ; "error 0"
.data:08000038 dd offset aSomeOtherError ; "some other error"
.data:0800003C dd offset aYetAnotherErro ; "yet another error"
.data:08000040 dd offset aEraseError ; "Erase error!"
.data:08000044 dd offset a____ ; "...."
.rodata:08000049 aUnusedString db 'unused string',0 ; DATA XREF: .data:unusedo
.rodata:08000057 aError0 db 'error 0',0 ; DATA XREF: .data:errorso
.rodata:0800005F aSomeOtherError db 'some other error',0 ; DATA XREF: .data:08000038o
.rodata:08000070 aYetAnotherErro db 'yet another error',0 ; DATA XREF: .data:0800003Co
.rodata:08000082 aEraseError db 'Erase error!',0 ; DATA XREF: .data:08000040o
.rodata:0800008F a____ db '....',0 ; DATA XREF: .data:08000044o
You see that each string has a pointer entry in the data
section, and the ascii data in the rodata
(read only data) section. And each of the ascii strings has an xref (cross reference) to the pointer that points to it - this is not a part of the binary; ida detects where each string is referenced, and generates the "backreferences", or xrefs.
The important thing is: you can use this to find the string table (errors, at 0x08000034
) if you have only the ascii bytes. And you can find where the string table itself is used by looking at its xref - from the print_error_message function. In contrast, the unused string does not have an xref, because it isn't used anywhere.
Ida will allow you to double-click on the xref to move to where it 'comes from' to navigate easily.
I'd check if you have an array of strings that starts a bit before the xref to your string, where it gets used, and possibly where the using function gets called.
Another possibility is something that i saw a few days ago in an ARM android shared library. The library had some strings holding function names, directly after each other, like this (translated to x86 syntax)
errmsg db 'Error in %s, file %s, line %d\n', 0
strtab db 'opencachefile', 0
db 'closecachefile', 0
db 'getcacheentry', 0
db 'putcacheentry', 0
db 'delcacheentry', 0
The function that got something from cache used the third of these strings to log a possible error. The code looked like this (again, translated from arm to x86):
...
mov eax, offset strtab
add eax, 29 ;<-- difference in bytes between 'open' and 'get'
push eax
mov eax, offset errmsg
push eax
call android_log_print
The other functions had similar constructs, so strtab
was referenced 5 times (one in each function), and the byte difference adjusted in each of them. I sincerely don't know why a compiler would do this, but just maybe something similar is going on in your code.