Output 64 bit integer with hexdump
Asked Answered
S

4

6

I currently work on some binary data. In order to check and debug the data previously generated by my application I use hexdump, facing the obstacle of hexdump not appearing to be able to extract a 64-bit integer field. Given the following minimal example:

#include <iostream>
#include <fstream>
#include <cstdint>

int main(int argc, char** argv){
    std::ofstream os("tmp.bin", std::ios::out | std::ios::binary);
    uint64_t x = 7;
    os.write((char*)&x,sizeof(uint64_t));
    os.close();
    return 0;
}

I perform a simple hexdump on my system:

hexdump tmp.bin

> 0000000: 0007 0000 0000 0000
> 0000008:

Now trying to extract the unsigned int of 64 bit width yields:

hexdump -e '/8 "%u"' tmp.bin

> hexdump: bad byte count for conversion character u

According to the well written hexdump-manual by David Mair it should be possible to do it, but I have no success.

What am I missing ?

Sacculate answered 26/6, 2015 at 20:7 Comment(8)
Unfortunately not as this only modifies the indentation width of the output.Sacculate
In the manpages it says only 4bytes are supported most for x and u. Anyway after a little bashing i found this workaround: hexdump -e '2/4 "%08X" "\n"' FILE | awk '{system("echo \"ibase=16; "$1"\"|bc")}' It basically prints two 4 byte hex pairs and then converts this to decimal with bc. I don't know if the order of the 2 hex pairs may need to swap for the correct value, but you could give it a try.Mouflon
All right, I just tried it out. The values had to be swapped indeed. This is how it works: hexdump -e '2/4 "%08X " "\n"' HEX | awk 'BEGIN{printf "ibase=16; "}{print $2 $1}' | bc Thank you.Sacculate
Ok, now I hit signed numbers. As I don't know if they are represented using a sign bit, one's complement, two's complement, offset binary or negative base representation it will be too much for a quick dump. So our solution will only work on unsigned 64 bit integers.Sacculate
I think we can check the most significant bit and if it is set, logical and the number with the mask 0x7FFFFFFFFFFFFFFF and subtract the result from the mask we should get the signed result i think.Mouflon
Well, I found a way to do it with the bash inherent calculator on the awk output. Apparently, bash's $(( )) knows how to transform it correctly.Sacculate
@Mouflon You may want to put the workaround as an answer: x=`hexdump -n 8 -e '2/4 "%08X " "\n"' $1 | awk 'BEGIN{printf "0x"}{print $2$1}'`; echo $(($x));Sacculate
Ultimately you came up with the answer ;)Mouflon
S
3

Our final workaround reads as follows:

x=`hexdump -n 8 -e '2/4 "%08X " "\n"' {FILENAME} | awk 'BEGIN{printf "0x"}{print $2$1}'`
echo $(($x))

Explaination for each part:

  • Extract the eight bytes of the 64-bit integer value from file {FILENAME} as two four byte chunks printed as hexadecimal encoded values.

    hexdump -n 8 -e '2/4 "%08X " "\n"' {FILENAME}
    
  • Reverses the byte order of the two chunks and prints it as a single eight byte chunk representing the binary value. Prepend 0x for the following processing.

    awk 'BEGIN{printf "0x"}{print $2$1}
    
  • Save the hexadecimal representation into x for bash to evaluate.

    x=`....`
    
  • Let the bourne shell interpret and output the hexadecimal encoded value of the 64-bit integer variable (here the previously prepended 0x is needed).

    echo $(($x))
    
Sacculate answered 6/7, 2015 at 13:9 Comment(1)
I was able to extend this, which was very useful.Text
V
1

One can use sed also. The following matches 8 byte hex integers and swaps them. Again this only works for unsigned integers.

hexdump ... | sed 's/0x\([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\)/0x\2\1/'

AFAICT one should be able to write much more clearly

hexdump ... | sed 's/0x\([0-9a-f]{8,8}\)\([0-9a-f]{8,8}\)/0x\2\1/'

typically with some command line option such as -E to enable extended regular expressions, but at least on Mac OS X 10.10 this doesn't work.

Virulence answered 24/10, 2017 at 18:3 Comment(0)
M
1

Try the "od" command instead. od -xL outputs long integer

Misreckon answered 5/3, 2020 at 9:59 Comment(0)
B
0

I don't understand why this doesn't work out-of-the-box, but I had the same problem printing 64-bit integers and ended up compiling a better version from util-linux found here: https://github.com/karelzak/util-linux. At first I tried installing that package in Ubuntu, but it didn't update hexdump, so I decided to try doing it "manually."

It's a bit of work, but not too bad. Just use git to grab the source, run the autogen.sh script, and then ./configure followed by make hexdump to compile just that program. Compiling only took 4 seconds on my laptop.

Barbey answered 6/2, 2020 at 9:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.