diff options
Diffstat (limited to 'documentation/libelf-by-example/prog5.txt')
-rw-r--r-- | documentation/libelf-by-example/prog5.txt | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/documentation/libelf-by-example/prog5.txt b/documentation/libelf-by-example/prog5.txt new file mode 100644 index 0000000000000..d44cf935fe1cb --- /dev/null +++ b/documentation/libelf-by-example/prog5.txt @@ -0,0 +1,133 @@ +/* + * Create an ELF object. + * + * $Id: prog5.txt 2133 2011-11-10 08:28:22Z jkoshy $ + */ + +#include <err.h> +#include <fcntl.h> +#include <libelf.h> @\co{1}@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +uint32_t hash_words[] = { @\co{2}@ + 0x01234567, + 0x89abcdef, + 0xdeadc0de +}; + +char string_table[] = { @\co{3}@ + /* Offset 0 */ '\0', + /* Offset 1 */ '.', 'f', 'o', 'o', '\0', + /* Offset 6 */ '.', 's', 'h', 's', 't', + 'r', 't', 'a', 'b', '\0' +}; + +int +main(int argc, char **argv) +{ + int fd; + Elf *e; + Elf_Scn *scn; + Elf_Data *data; + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdr; + Elf32_Shdr *shdr; + + if (argc != 2) + errx(EXIT_FAILURE, "usage: %s file-name", argv[0]); + + if (elf_version(EV_CURRENT) == EV_NONE) + errx(EXIT_FAILURE, "ELF library initialization " + "failed: %s", elf_errmsg(-1)); + + if ((fd = open(argv[1], O_WRONLY|O_CREAT, 0777)) < 0) @\co{4}@ + err(EXIT_FAILURE, "open \%s\" failed", argv[1]); + + if ((e = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) @\co{5}@ + errx(EXIT_FAILURE, "elf_begin() failed: %s.", + elf_errmsg(-1)); + + if ((ehdr = elf32_newehdr(e)) == NULL) @\co{6}@ + errx(EXIT_FAILURE, "elf32_newehdr() failed: %s.", + elf_errmsg(-1)); + + ehdr->e_ident[EI_DATA] = ELFDATA2MSB; + ehdr->e_machine = EM_PPC; /* 32-bit PowerPC object */ + ehdr->e_type = ET_EXEC; + + if ((phdr = elf32_newphdr(e, 1)) == NULL) @\co{7}@ + errx(EXIT_FAILURE, "elf32_newphdr() failed: %s.", + elf_errmsg(-1)); + + if ((scn = elf_newscn(e)) == NULL) @\co{8}@ + errx(EXIT_FAILURE, "elf_newscn() failed: %s.", + elf_errmsg(-1)); + + if ((data = elf_newdata(scn)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s.", + elf_errmsg(-1)); + + data->d_align = 4; + data->d_off = 0LL; + data->d_buf = hash_words; + data->d_type = ELF_T_WORD; + data->d_size = sizeof(hash_words); + data->d_version = EV_CURRENT; + + if ((shdr = elf32_getshdr(scn)) == NULL) + errx(EXIT_FAILURE, "elf32_getshdr() failed: %s.", + elf_errmsg(-1)); + + shdr->sh_name = 1; + shdr->sh_type = SHT_HASH; + shdr->sh_flags = SHF_ALLOC; + shdr->sh_entsize = 0; + + if ((scn = elf_newscn(e)) == NULL) @\co{9}@ + errx(EXIT_FAILURE, "elf_newscn() failed: %s.", + elf_errmsg(-1)); + + if ((data = elf_newdata(scn)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s.", + elf_errmsg(-1)); + + data->d_align = 1; + data->d_buf = string_table; + data->d_off = 0LL; + data->d_size = sizeof(string_table); + data->d_type = ELF_T_BYTE; + data->d_version = EV_CURRENT; + + if ((shdr = elf32_getshdr(scn)) == NULL) + errx(EXIT_FAILURE, "elf32_getshdr() failed: %s.", + elf_errmsg(-1)); + + shdr->sh_name = 6; + shdr->sh_type = SHT_STRTAB; + shdr->sh_flags = SHF_STRINGS | SHF_ALLOC; + shdr->sh_entsize = 0; + + elf_setshstrndx(e, elf_ndxscn(scn)); @\co{10}@ + + if (elf_update(e, ELF_C_NULL) < 0) @\co{11}@ + errx(EXIT_FAILURE, "elf_update(NULL) failed: %s.", + elf_errmsg(-1)); + + phdr->p_type = PT_PHDR; + phdr->p_offset = ehdr->e_phoff; + phdr->p_filesz = elf32_fsize(ELF_T_PHDR, 1, EV_CURRENT); + + (void) elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); + + if (elf_update(e, ELF_C_WRITE) < 0) @\co{12}@ + errx(EXIT_FAILURE, "elf_update() failed: %s.", + elf_errmsg(-1)); + + (void) elf_end(e); + (void) close(fd); + + exit(EXIT_SUCCESS); +} + |