1/* Test program for extracting ELF Note headers and getting whole notes. 2 Copyright (C) 2019 Red Hat, Inc. 3 This file is part of elfutils. 4 5 This file is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#ifdef HAVE_CONFIG_H 19# include <config.h> 20#endif 21 22#include <errno.h> 23#include <fcntl.h> 24#include <inttypes.h> 25#include <stdio.h> 26#include <stdlib.h> 27#include <string.h> 28#include <unistd.h> 29 30#include ELFUTILS_HEADER(elf) 31#include <gelf.h> 32 33int 34main (int argc, char *argv[]) 35{ 36 if (argc != 2) 37 { 38 printf ("No ELF file given as argument\n"); 39 exit (1); 40 } 41 42 const char *fname = argv[1]; 43 44 // Initialize libelf. 45 elf_version (EV_CURRENT); 46 47 /* Read the ELF from disk now. */ 48 int fd = open (fname, O_RDONLY); 49 if (fd == -1) 50 { 51 printf ("cannot open '%s': %s\n", fname, strerror (errno)); 52 exit (1); 53 } 54 55 Elf *elf = elf_begin (fd, ELF_C_READ, NULL); 56 if (elf == NULL) 57 { 58 printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); 59 exit (1); 60 } 61 62 GElf_Ehdr ehdr; 63 if (gelf_getehdr (elf, &ehdr) == NULL) 64 { 65 printf ("cannot get Ehdr: %s\n", elf_errmsg (-1)); 66 exit (1); 67 } 68 69 /* Search for all SHT_NOTE sections. */ 70 Elf_Scn *scn = NULL; 71 while ((scn = elf_nextscn (elf, scn)) != NULL) 72 { 73 /* Get the header. */ 74 GElf_Shdr shdr; 75 if (gelf_getshdr (scn, &shdr) == NULL) 76 { 77 printf ("couldn't get shdr: %s\n", elf_errmsg (-1)); 78 exit (1); 79 } 80 81 if (shdr.sh_type == SHT_NOTE) 82 { 83 printf ("Notes in section %zd:\n", elf_ndxscn (scn)); 84 85 Elf_Data *raw = elf_rawdata (scn, NULL); 86 if (raw == NULL) 87 { 88 printf ("couldn't get raw data: %s\n", elf_errmsg (-1)); 89 exit (1); 90 } 91 92 Elf_Data *data = elf_getdata (scn, NULL); 93 if (data == NULL) 94 { 95 printf ("couldn't get data: %s\n", elf_errmsg (-1)); 96 exit (1); 97 } 98 99 size_t off = 0; 100 size_t next; 101 GElf_Nhdr nhdr; 102 size_t n_off; 103 size_t d_off; 104 while ((next = gelf_getnote (data, off, &nhdr, &n_off, &d_off)) > 0) 105 { 106 /* Now just get the note header "raw" (don't 107 copy/translate the note data). This only handles 108 traditional GNU ELF Notes, so we still use the next 109 from gelf_getnote (padding is different for new style 110 ELF_T_NHDR8 notes). */ 111 Elf32_Nhdr nh; 112 Elf_Data src = 113 { 114 .d_version = EV_CURRENT, .d_type = ELF_T_NHDR, 115 .d_size = sizeof nh 116 }; 117 Elf_Data dst = src; 118 src.d_buf = raw->d_buf + off; 119 dst.d_buf = &nh; 120 121 if (elf32_xlatetom (&dst, &src, ehdr.e_ident[EI_DATA]) == NULL) 122 { 123 printf ("couldn't xlate note: %s\n", elf_errmsg (-1)); 124 exit (1); 125 } 126 127 printf ("type: %" PRId32 ",%" PRId32 128 ", namesz: %" PRId32 ",%" PRId32 129 ", descsz: %" PRId32 ",%" PRId32 "\n", 130 nhdr.n_type, nh.n_type, 131 nhdr.n_namesz, nh.n_namesz, 132 nhdr.n_descsz, nh.n_descsz); 133 134 if (nhdr.n_type != nh.n_type 135 || nhdr.n_namesz != nh.n_namesz 136 || nhdr.n_descsz != nh.n_descsz) 137 { 138 printf ("Nhdrs not equal!\n"); 139 exit (1); 140 } 141 142 off = next; 143 } 144 } 145 146 } 147 148 if (elf_end (elf) != 0) 149 { 150 printf ("failure in elf_end: %s\n", elf_errmsg (-1)); 151 exit (1); 152 } 153 154 close (fd); 155 156 return 0; 157} 158