Binary Output from a C/C++ Function

Just a quick post to demonstrate a script that can be used to generate the binary form of a C/C++ function on Linux. It prints both the disassembled code and a “C array” (array of hexadecimal bytes suitable for a .h file) of the function.

#! /bin/bash

# print_function_binary functionName binaryName
# Author: Samuel Ellicott 2022-11-16
# Outputs the disassembled and hex form of a C function to the command line 

function_name=$1
binary_name=$2

# Get the function memory offset and length
function_entry=`objdump -t $binary_name | grep -P "$function_name([^@]|$)"`
output=$(echo $function_entry | sed -En -e 's/^(\w*)(\s*[.[:alnum:]]*){3}\s*(\w*).*$/0x\1 0x\3/p')
read begin length <<<$output
end=$(( begin + length ))

# get the function file offset
code_offset=$(readelf -l a.out | grep LOAD | head -n 1 | sed -En -e 's/^\s*LOAD\s*\w*\s*(\w*).*$/\1/p')

file_begin=$(( begin - code_offset ))

echo "Dissembled Output"
objdump -d --start-address=$begin --stop-address=$end $binary_name | tail -n +7
echo ""

echo "C Output"
xxd -i -s $file_begin -l $length $binary_name

When used on an example piece of code

// main.c
int intFunc(void) {
    return 42;
}

int main(void) {
    int ret_val;
    ret_val = intFunc();
    return ret_val; 
}

We get the following output for “intFunc” and “main” (when compiled to a.out by g++)

$ gcc main.c
$ ./print_function_binary intFunc a.out
Dissembled Output
000000000040050d <_Z7intFuncif>:
  40050d:	55                   	push   %rbp
  40050e:	48 89 e5             	mov    %rsp,%rbp
  400511:	89 7d fc             	mov    %edi,-0x4(%rbp)
  400514:	f3 0f 11 45 f8       	movss  %xmm0,-0x8(%rbp)
  400519:	8b 45 fc             	mov    -0x4(%rbp),%eax
  40051c:	5d                   	pop    %rbp
  40051d:	c3                   	retq   

C Output
unsigned char a_out[] = {
  0x55, 0x48, 0x89, 0xe5, 0x89, 0x7d, 0xfc, 0xf3, 0x0f, 0x11, 0x45, 0xf8,
  0x8b, 0x45, 0xfc, 0x5d, 0xc3
};
unsigned int a_out_len = 17;
$
$ ./print_function_binary main a.out
Dissasembled Output
000000000040051e <main>:
  40051e:	55                   	push   %rbp
  40051f:	48 89 e5             	mov    %rsp,%rbp
  400522:	48 83 ec 10          	sub    $0x10,%rsp
  400526:	0f 57 c0             	xorps  %xmm0,%xmm0
  400529:	bf 2a 00 00 00       	mov    $0x2a,%edi
  40052e:	e8 da ff ff ff       	callq  40050d <_Z7intFuncif>
  400533:	89 45 fc             	mov    %eax,-0x4(%rbp)
  400536:	8b 45 fc             	mov    -0x4(%rbp),%eax
  400539:	c9                   	leaveq 
  40053a:	c3                   	retq   

C Output
unsigned char a_out[] = {
  0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x10, 0x0f, 0x57, 0xc0, 0xbf,
  0x2a, 0x00, 0x00, 0x00, 0xe8, 0xda, 0xff, 0xff, 0xff, 0x89, 0x45, 0xfc,
  0x8b, 0x45, 0xfc, 0xc9, 0xc3
};
unsigned int a_out_len = 29;