Upon decompiling various programs (which I do not have the source for), I have found some interesting sequences of code. A program has a c-string (str
) defined in the DATA section. In some function in the TEXT section, a part of that string is set by moving a hexadecimal number to a position in the string (simplified Intel assembly MOV str,0x006f6c6c6568
). Here is an snippet in C:
#include <stdio.h>
static char str[16];
int main(void)
{
*(long *)str = 0x006f6c6c6568;
printf("%s\n", str);
return 0;
}
I am running macOS, which uses little endian, so 0x006f6c6c6568
translates to hello
. The program compiles with no errors or warnings, and when run, prints out hello
as expected. I calculated 0x006f6c6c6568
by hand, but I was wondering if C could do it for me. Something like this is what I mean:
#include <stdio.h>
static char str[16];
int main(void)
{
// *(long *)str = 0x006f6c6c6568;
*(str 0) = "hello";
printf("%s\n", str);
return 0;
}
Now, I would not like to treat "hello"
as a string literal, it might be treated like this for little-endian:
*(long *)str = (long)(((long)'h') |
((long)'e' << 8) |
((long)'l' << 16) |
((long)'l' << 24) |
((long)'o' << 32) |
((long)0 << 40));
Or, if compiled for a big-endian target, this:
*(long *)str = (long)((0 |
((long)'o' << 8) |
((long)'l' << 16) |
((long)'l' << 24) |
((long)'e' << 32) |
((long)'h' << 40));
Thoughts?
CodePudding user response:
is there some built-in C function/method/preprocessor function/operator/etc. that can convert an 8 character string into its raw hexadecimal representation of long type
I see you've already accepted an answer, but I think this solution is easier to understand and probably what you want.
Copying the string bytes into a 64-bit integer type is all that's needed. I'm going to use uint64_t
instead of long
as that's guaranteed to be 8 bytes on all platforms. long
is often only 4 bytes.
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
uint64_t packString(const char* str) {
uint64_t value = 0;
size_t copy = str ? strnlen(str, sizeof(value)) : 0; // copy over at most 8 bytes
memcpy(&value, str, copy);
return value;
}
Example:
int main() {
printf("0x%" PRIx64 "\n", packString("hello"));
return 0;
}
Then build and run:
$:~/code/packString$ g main.cpp -o main
$:~/code/packString$ ./main
0x6f6c6c6568
CodePudding user response:
Add #if __BYTE_ORDER__
to judge, like this:
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
*(long *)str = (long)(((long)'h') |
((long)'e' << 8) |
((long)'l' << 16) |
((long)'l' << 24) |
((long)'o' << 32) |
((long)0 << 40));
#else
*(long *)str = (long)((0 |
((long)'o' << 8) |
((long)'l' << 16) |
((long)'l' << 24) |
((long)'e' << 32) |
((long)'h' << 40));
#endif