Basically, this is the code that I wrote based on the answer to my question. In order to compile the code, I had to make some changes, and I hope that it will work as many types of platforms as possible. However, it was tested on only one machine. One of the assumptions I used was that the program was built on a machine that runs it, so you should not check compatibility between the program and the machine.
user@ :~/$ uname -s -r -m -o Linux 3.2.0-45-generic x86_64 GNU/Linux user@ :~/$ g++ test.cpp -o test user@ :~/$ readelf -n test | grep Build Build ID: dc5c4682e0282e2bd8bc2d3b61cfe35826aa34fc user@ :~/$ ./test Build ID: dc5c4682e0282e2bd8bc2d3b61cfe35826aa34fc
#include <elf.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <sys/stat.h> #if __x86_64__ # define ElfW(type) Elf64_##type #else # define ElfW(type) Elf32_##type #endif /* detecting build id of a program from its note section http://stackoverflow.com/questions/17637745/can-a-program-read-its-own-elf-section http://www.scs.stanford.edu/histar/src/pkg/uclibc/utils/readelf.c http://www.sco.com/developers/gabi/2000-07-17/ch5.pheader.html#note_section */ int main (int argc, char* argv[]) { char *thefilename = argv[0]; FILE *thefile; struct stat statbuf; ElfW(Ehdr) *ehdr = 0; ElfW(Phdr) *phdr = 0; ElfW(Nhdr) *nhdr = 0; if (!(thefile = fopen(thefilename, "r"))) { perror(thefilename); exit(EXIT_FAILURE); } if (fstat(fileno(thefile), &statbuf) < 0) { perror(thefilename); exit(EXIT_FAILURE); } ehdr = (ElfW(Ehdr) *)mmap(0, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0); phdr = (ElfW(Phdr) *)(ehdr->e_phoff + (size_t)ehdr); while (phdr->p_type != PT_NOTE) { ++phdr; } nhdr = (ElfW(Nhdr) *)(phdr->p_offset + (size_t)ehdr); while (nhdr->n_type != NT_GNU_BUILD_ID) { nhdr = (ElfW(Nhdr) *)((size_t)nhdr + sizeof(ElfW(Nhdr)) + nhdr->n_namesz + nhdr->n_descsz); } unsigned char * build_id = (unsigned char *)malloc(nhdr->n_descsz); memcpy(build_id, (void *)((size_t)nhdr + sizeof(ElfW(Nhdr)) + nhdr->n_namesz), nhdr->n_descsz); printf(" Build ID: "); for (int i = 0 ; i < nhdr->n_descsz ; ++i) { printf("%02x",build_id[i]); } free(build_id); printf("\n"); return 0; }
source share