1da0c48c4Sopenharmony_ci/* Print contents of object file note. 2da0c48c4Sopenharmony_ci Copyright (C) 2002, 2007, 2009, 2011, 2015, 2016, 2018 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci Written by Ulrich Drepper <drepper@redhat.com>, 2002. 5da0c48c4Sopenharmony_ci 6da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 7da0c48c4Sopenharmony_ci it under the terms of either 8da0c48c4Sopenharmony_ci 9da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 10da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 11da0c48c4Sopenharmony_ci your option) any later version 12da0c48c4Sopenharmony_ci 13da0c48c4Sopenharmony_ci or 14da0c48c4Sopenharmony_ci 15da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 16da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 17da0c48c4Sopenharmony_ci your option) any later version 18da0c48c4Sopenharmony_ci 19da0c48c4Sopenharmony_ci or both in parallel, as here. 20da0c48c4Sopenharmony_ci 21da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 22da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 23da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24da0c48c4Sopenharmony_ci General Public License for more details. 25da0c48c4Sopenharmony_ci 26da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 27da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 28da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 29da0c48c4Sopenharmony_ci 30da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 31da0c48c4Sopenharmony_ci# include <config.h> 32da0c48c4Sopenharmony_ci#endif 33da0c48c4Sopenharmony_ci 34da0c48c4Sopenharmony_ci#include <inttypes.h> 35da0c48c4Sopenharmony_ci#include <stdio.h> 36da0c48c4Sopenharmony_ci#include <stdlib.h> 37da0c48c4Sopenharmony_ci#include <string.h> 38da0c48c4Sopenharmony_ci#include <libeblP.h> 39da0c48c4Sopenharmony_ci 40da0c48c4Sopenharmony_ci#include "common.h" 41da0c48c4Sopenharmony_ci#include "libelfP.h" 42da0c48c4Sopenharmony_ci#include "libdwP.h" 43da0c48c4Sopenharmony_ci#include "memory-access.h" 44da0c48c4Sopenharmony_ci 45da0c48c4Sopenharmony_ci 46da0c48c4Sopenharmony_civoid 47da0c48c4Sopenharmony_ciebl_object_note (Ebl *ebl, uint32_t namesz, const char *name, uint32_t type, 48da0c48c4Sopenharmony_ci uint32_t descsz, const char *desc) 49da0c48c4Sopenharmony_ci{ 50da0c48c4Sopenharmony_ci if (! ebl->object_note (name, type, descsz, desc)) 51da0c48c4Sopenharmony_ci { 52da0c48c4Sopenharmony_ci /* The machine specific function did not know this type. */ 53da0c48c4Sopenharmony_ci 54da0c48c4Sopenharmony_ci if (strcmp ("stapsdt", name) == 0) 55da0c48c4Sopenharmony_ci { 56da0c48c4Sopenharmony_ci if (type != 3) 57da0c48c4Sopenharmony_ci { 58da0c48c4Sopenharmony_ci printf (_("unknown SDT version %u\n"), type); 59da0c48c4Sopenharmony_ci return; 60da0c48c4Sopenharmony_ci } 61da0c48c4Sopenharmony_ci 62da0c48c4Sopenharmony_ci /* Descriptor starts with three addresses, pc, base ref and 63da0c48c4Sopenharmony_ci semaphore. Then three zero terminated strings provider, 64da0c48c4Sopenharmony_ci name and arguments. */ 65da0c48c4Sopenharmony_ci 66da0c48c4Sopenharmony_ci union 67da0c48c4Sopenharmony_ci { 68da0c48c4Sopenharmony_ci Elf64_Addr a64[3]; 69da0c48c4Sopenharmony_ci Elf32_Addr a32[3]; 70da0c48c4Sopenharmony_ci } addrs; 71da0c48c4Sopenharmony_ci 72da0c48c4Sopenharmony_ci size_t addrs_size = gelf_fsize (ebl->elf, ELF_T_ADDR, 3, EV_CURRENT); 73da0c48c4Sopenharmony_ci if (descsz < addrs_size + 3) 74da0c48c4Sopenharmony_ci { 75da0c48c4Sopenharmony_ci invalid_sdt: 76da0c48c4Sopenharmony_ci printf (_("invalid SDT probe descriptor\n")); 77da0c48c4Sopenharmony_ci return; 78da0c48c4Sopenharmony_ci } 79da0c48c4Sopenharmony_ci 80da0c48c4Sopenharmony_ci Elf_Data src = 81da0c48c4Sopenharmony_ci { 82da0c48c4Sopenharmony_ci .d_type = ELF_T_ADDR, .d_version = EV_CURRENT, 83da0c48c4Sopenharmony_ci .d_buf = (void *) desc, .d_size = addrs_size 84da0c48c4Sopenharmony_ci }; 85da0c48c4Sopenharmony_ci 86da0c48c4Sopenharmony_ci Elf_Data dst = 87da0c48c4Sopenharmony_ci { 88da0c48c4Sopenharmony_ci .d_type = ELF_T_ADDR, .d_version = EV_CURRENT, 89da0c48c4Sopenharmony_ci .d_buf = &addrs, .d_size = addrs_size 90da0c48c4Sopenharmony_ci }; 91da0c48c4Sopenharmony_ci 92da0c48c4Sopenharmony_ci if (gelf_xlatetom (ebl->elf, &dst, &src, 93da0c48c4Sopenharmony_ci elf_getident (ebl->elf, NULL)[EI_DATA]) == NULL) 94da0c48c4Sopenharmony_ci { 95da0c48c4Sopenharmony_ci printf ("%s\n", elf_errmsg (-1)); 96da0c48c4Sopenharmony_ci return; 97da0c48c4Sopenharmony_ci } 98da0c48c4Sopenharmony_ci 99da0c48c4Sopenharmony_ci const char *provider = desc + addrs_size; 100da0c48c4Sopenharmony_ci const char *pname = memchr (provider, '\0', desc + descsz - provider); 101da0c48c4Sopenharmony_ci if (pname == NULL) 102da0c48c4Sopenharmony_ci goto invalid_sdt; 103da0c48c4Sopenharmony_ci 104da0c48c4Sopenharmony_ci ++pname; 105da0c48c4Sopenharmony_ci const char *args = memchr (pname, '\0', desc + descsz - pname); 106da0c48c4Sopenharmony_ci if (args == NULL || 107da0c48c4Sopenharmony_ci memchr (++args, '\0', desc + descsz - pname) != desc + descsz - 1) 108da0c48c4Sopenharmony_ci goto invalid_sdt; 109da0c48c4Sopenharmony_ci 110da0c48c4Sopenharmony_ci GElf_Addr pc; 111da0c48c4Sopenharmony_ci GElf_Addr base; 112da0c48c4Sopenharmony_ci GElf_Addr sem; 113da0c48c4Sopenharmony_ci if (gelf_getclass (ebl->elf) == ELFCLASS32) 114da0c48c4Sopenharmony_ci { 115da0c48c4Sopenharmony_ci pc = addrs.a32[0]; 116da0c48c4Sopenharmony_ci base = addrs.a32[1]; 117da0c48c4Sopenharmony_ci sem = addrs.a32[2]; 118da0c48c4Sopenharmony_ci } 119da0c48c4Sopenharmony_ci else 120da0c48c4Sopenharmony_ci { 121da0c48c4Sopenharmony_ci pc = addrs.a64[0]; 122da0c48c4Sopenharmony_ci base = addrs.a64[1]; 123da0c48c4Sopenharmony_ci sem = addrs.a64[2]; 124da0c48c4Sopenharmony_ci } 125da0c48c4Sopenharmony_ci 126da0c48c4Sopenharmony_ci printf (_(" PC: ")); 127da0c48c4Sopenharmony_ci printf ("%#" PRIx64 ",", pc); 128da0c48c4Sopenharmony_ci printf (_(" Base: ")); 129da0c48c4Sopenharmony_ci printf ("%#" PRIx64 ",", base); 130da0c48c4Sopenharmony_ci printf (_(" Semaphore: ")); 131da0c48c4Sopenharmony_ci printf ("%#" PRIx64 "\n", sem); 132da0c48c4Sopenharmony_ci printf (_(" Provider: ")); 133da0c48c4Sopenharmony_ci printf ("%s,", provider); 134da0c48c4Sopenharmony_ci printf (_(" Name: ")); 135da0c48c4Sopenharmony_ci printf ("%s,", pname); 136da0c48c4Sopenharmony_ci printf (_(" Args: ")); 137da0c48c4Sopenharmony_ci printf ("'%s'\n", args); 138da0c48c4Sopenharmony_ci return; 139da0c48c4Sopenharmony_ci } 140da0c48c4Sopenharmony_ci 141da0c48c4Sopenharmony_ci if (strncmp (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX, 142da0c48c4Sopenharmony_ci strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0 143da0c48c4Sopenharmony_ci && (type == NT_GNU_BUILD_ATTRIBUTE_OPEN 144da0c48c4Sopenharmony_ci || type == NT_GNU_BUILD_ATTRIBUTE_FUNC)) 145da0c48c4Sopenharmony_ci { 146da0c48c4Sopenharmony_ci /* There might or might not be a pair of addresses in the desc. */ 147da0c48c4Sopenharmony_ci if (descsz > 0) 148da0c48c4Sopenharmony_ci { 149da0c48c4Sopenharmony_ci printf (" Address Range: "); 150da0c48c4Sopenharmony_ci 151da0c48c4Sopenharmony_ci union 152da0c48c4Sopenharmony_ci { 153da0c48c4Sopenharmony_ci Elf64_Addr a64[2]; 154da0c48c4Sopenharmony_ci Elf32_Addr a32[2]; 155da0c48c4Sopenharmony_ci } addrs; 156da0c48c4Sopenharmony_ci 157da0c48c4Sopenharmony_ci size_t addr_size = gelf_fsize (ebl->elf, ELF_T_ADDR, 158da0c48c4Sopenharmony_ci 2, EV_CURRENT); 159da0c48c4Sopenharmony_ci if (descsz != addr_size) 160da0c48c4Sopenharmony_ci printf ("<unknown data>\n"); 161da0c48c4Sopenharmony_ci else 162da0c48c4Sopenharmony_ci { 163da0c48c4Sopenharmony_ci Elf_Data src = 164da0c48c4Sopenharmony_ci { 165da0c48c4Sopenharmony_ci .d_type = ELF_T_ADDR, .d_version = EV_CURRENT, 166da0c48c4Sopenharmony_ci .d_buf = (void *) desc, .d_size = descsz 167da0c48c4Sopenharmony_ci }; 168da0c48c4Sopenharmony_ci 169da0c48c4Sopenharmony_ci Elf_Data dst = 170da0c48c4Sopenharmony_ci { 171da0c48c4Sopenharmony_ci .d_type = ELF_T_ADDR, .d_version = EV_CURRENT, 172da0c48c4Sopenharmony_ci .d_buf = &addrs, .d_size = descsz 173da0c48c4Sopenharmony_ci }; 174da0c48c4Sopenharmony_ci 175da0c48c4Sopenharmony_ci if (gelf_xlatetom (ebl->elf, &dst, &src, 176da0c48c4Sopenharmony_ci elf_getident (ebl->elf, 177da0c48c4Sopenharmony_ci NULL)[EI_DATA]) == NULL) 178da0c48c4Sopenharmony_ci printf ("%s\n", elf_errmsg (-1)); 179da0c48c4Sopenharmony_ci else 180da0c48c4Sopenharmony_ci { 181da0c48c4Sopenharmony_ci if (addr_size == 4) 182da0c48c4Sopenharmony_ci printf ("%#" PRIx32 " - %#" PRIx32 "\n", 183da0c48c4Sopenharmony_ci addrs.a32[0], addrs.a32[1]); 184da0c48c4Sopenharmony_ci else 185da0c48c4Sopenharmony_ci printf ("%#" PRIx64 " - %#" PRIx64 "\n", 186da0c48c4Sopenharmony_ci addrs.a64[0], addrs.a64[1]); 187da0c48c4Sopenharmony_ci } 188da0c48c4Sopenharmony_ci } 189da0c48c4Sopenharmony_ci } 190da0c48c4Sopenharmony_ci 191da0c48c4Sopenharmony_ci /* Most data actually is inside the name. 192da0c48c4Sopenharmony_ci https://fedoraproject.org/wiki/Toolchain/Watermark */ 193da0c48c4Sopenharmony_ci 194da0c48c4Sopenharmony_ci /* We need at least 2 chars of data to describe the 195da0c48c4Sopenharmony_ci attribute and value encodings. */ 196da0c48c4Sopenharmony_ci const char *data = (name 197da0c48c4Sopenharmony_ci + strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)); 198da0c48c4Sopenharmony_ci if (namesz < 2) 199da0c48c4Sopenharmony_ci { 200da0c48c4Sopenharmony_ci printf ("<insufficient data>\n"); 201da0c48c4Sopenharmony_ci return; 202da0c48c4Sopenharmony_ci } 203da0c48c4Sopenharmony_ci 204da0c48c4Sopenharmony_ci printf (" "); 205da0c48c4Sopenharmony_ci 206da0c48c4Sopenharmony_ci /* In most cases the value comes right after the encoding bytes. */ 207da0c48c4Sopenharmony_ci const char *value = &data[2]; 208da0c48c4Sopenharmony_ci switch (data[1]) 209da0c48c4Sopenharmony_ci { 210da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_VERSION: 211da0c48c4Sopenharmony_ci printf ("VERSION: "); 212da0c48c4Sopenharmony_ci break; 213da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_STACK_PROT: 214da0c48c4Sopenharmony_ci printf ("STACK_PROT: "); 215da0c48c4Sopenharmony_ci break; 216da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_RELRO: 217da0c48c4Sopenharmony_ci printf ("RELRO: "); 218da0c48c4Sopenharmony_ci break; 219da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_STACK_SIZE: 220da0c48c4Sopenharmony_ci printf ("STACK_SIZE: "); 221da0c48c4Sopenharmony_ci break; 222da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_TOOL: 223da0c48c4Sopenharmony_ci printf ("TOOL: "); 224da0c48c4Sopenharmony_ci break; 225da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_ABI: 226da0c48c4Sopenharmony_ci printf ("ABI: "); 227da0c48c4Sopenharmony_ci break; 228da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_PIC: 229da0c48c4Sopenharmony_ci printf ("PIC: "); 230da0c48c4Sopenharmony_ci break; 231da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_SHORT_ENUM: 232da0c48c4Sopenharmony_ci printf ("SHORT_ENUM: "); 233da0c48c4Sopenharmony_ci break; 234da0c48c4Sopenharmony_ci case 32 ... 126: 235da0c48c4Sopenharmony_ci printf ("\"%s\": ", &data[1]); 236da0c48c4Sopenharmony_ci value += strlen (&data[1]) + 1; 237da0c48c4Sopenharmony_ci break; 238da0c48c4Sopenharmony_ci default: 239da0c48c4Sopenharmony_ci printf ("<unknown>: "); 240da0c48c4Sopenharmony_ci break; 241da0c48c4Sopenharmony_ci } 242da0c48c4Sopenharmony_ci 243da0c48c4Sopenharmony_ci switch (data[0]) 244da0c48c4Sopenharmony_ci { 245da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC: 246da0c48c4Sopenharmony_ci { 247da0c48c4Sopenharmony_ci /* Any numbers are always in (unsigned) little endian. */ 248da0c48c4Sopenharmony_ci static const Dwarf dbg 249da0c48c4Sopenharmony_ci = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB }; 250da0c48c4Sopenharmony_ci size_t bytes = namesz - (value - name); 251da0c48c4Sopenharmony_ci uint64_t val; 252da0c48c4Sopenharmony_ci if (bytes == 1) 253da0c48c4Sopenharmony_ci val = *(unsigned char *) value; 254da0c48c4Sopenharmony_ci else if (bytes == 2) 255da0c48c4Sopenharmony_ci val = read_2ubyte_unaligned (&dbg, value); 256da0c48c4Sopenharmony_ci else if (bytes == 4) 257da0c48c4Sopenharmony_ci val = read_4ubyte_unaligned (&dbg, value); 258da0c48c4Sopenharmony_ci else if (bytes == 8) 259da0c48c4Sopenharmony_ci val = read_8ubyte_unaligned (&dbg, value); 260da0c48c4Sopenharmony_ci else 261da0c48c4Sopenharmony_ci goto unknown; 262da0c48c4Sopenharmony_ci printf ("%" PRIx64, val); 263da0c48c4Sopenharmony_ci } 264da0c48c4Sopenharmony_ci break; 265da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_TYPE_STRING: 266da0c48c4Sopenharmony_ci printf ("\"%s\"", value); 267da0c48c4Sopenharmony_ci break; 268da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE: 269da0c48c4Sopenharmony_ci printf ("TRUE"); 270da0c48c4Sopenharmony_ci break; 271da0c48c4Sopenharmony_ci case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE: 272da0c48c4Sopenharmony_ci printf ("FALSE"); 273da0c48c4Sopenharmony_ci break; 274da0c48c4Sopenharmony_ci default: 275da0c48c4Sopenharmony_ci { 276da0c48c4Sopenharmony_ci unknown: 277da0c48c4Sopenharmony_ci printf ("<unknown>"); 278da0c48c4Sopenharmony_ci } 279da0c48c4Sopenharmony_ci break; 280da0c48c4Sopenharmony_ci } 281da0c48c4Sopenharmony_ci 282da0c48c4Sopenharmony_ci printf ("\n"); 283da0c48c4Sopenharmony_ci 284da0c48c4Sopenharmony_ci return; 285da0c48c4Sopenharmony_ci } 286da0c48c4Sopenharmony_ci 287da0c48c4Sopenharmony_ci /* NT_VERSION doesn't have any info. All data is in the name. */ 288da0c48c4Sopenharmony_ci if (descsz == 0 && type == NT_VERSION) 289da0c48c4Sopenharmony_ci return; 290da0c48c4Sopenharmony_ci 291da0c48c4Sopenharmony_ci if (strcmp ("FDO", name) == 0 && type == NT_FDO_PACKAGING_METADATA 292da0c48c4Sopenharmony_ci && descsz > 0 && desc[descsz - 1] == '\0') 293da0c48c4Sopenharmony_ci printf(" Packaging Metadata: %.*s\n", (int) descsz, desc); 294da0c48c4Sopenharmony_ci 295da0c48c4Sopenharmony_ci /* Everything else should have the "GNU" owner name. */ 296da0c48c4Sopenharmony_ci if (strcmp ("GNU", name) != 0) 297da0c48c4Sopenharmony_ci return; 298da0c48c4Sopenharmony_ci 299da0c48c4Sopenharmony_ci switch (type) 300da0c48c4Sopenharmony_ci { 301da0c48c4Sopenharmony_ci case NT_GNU_BUILD_ID: 302da0c48c4Sopenharmony_ci if (strcmp (name, "GNU") == 0 && descsz > 0) 303da0c48c4Sopenharmony_ci { 304da0c48c4Sopenharmony_ci printf (_(" Build ID: ")); 305da0c48c4Sopenharmony_ci uint_fast32_t i; 306da0c48c4Sopenharmony_ci for (i = 0; i < descsz - 1; ++i) 307da0c48c4Sopenharmony_ci printf ("%02" PRIx8, (uint8_t) desc[i]); 308da0c48c4Sopenharmony_ci printf ("%02" PRIx8 "\n", (uint8_t) desc[i]); 309da0c48c4Sopenharmony_ci } 310da0c48c4Sopenharmony_ci break; 311da0c48c4Sopenharmony_ci 312da0c48c4Sopenharmony_ci case NT_GNU_GOLD_VERSION: 313da0c48c4Sopenharmony_ci if (strcmp (name, "GNU") == 0 && descsz > 0) 314da0c48c4Sopenharmony_ci /* A non-null terminated version string. */ 315da0c48c4Sopenharmony_ci printf (_(" Linker version: %.*s\n"), 316da0c48c4Sopenharmony_ci (int) descsz, desc); 317da0c48c4Sopenharmony_ci break; 318da0c48c4Sopenharmony_ci 319da0c48c4Sopenharmony_ci case NT_GNU_PROPERTY_TYPE_0: 320da0c48c4Sopenharmony_ci if (strcmp (name, "GNU") == 0 && descsz > 0) 321da0c48c4Sopenharmony_ci { 322da0c48c4Sopenharmony_ci /* There are at least 2 words. type and datasz. */ 323da0c48c4Sopenharmony_ci while (descsz >= 8) 324da0c48c4Sopenharmony_ci { 325da0c48c4Sopenharmony_ci struct pr_prop 326da0c48c4Sopenharmony_ci { 327da0c48c4Sopenharmony_ci GElf_Word pr_type; 328da0c48c4Sopenharmony_ci GElf_Word pr_datasz; 329da0c48c4Sopenharmony_ci } prop; 330da0c48c4Sopenharmony_ci 331da0c48c4Sopenharmony_ci Elf_Data in = 332da0c48c4Sopenharmony_ci { 333da0c48c4Sopenharmony_ci .d_version = EV_CURRENT, 334da0c48c4Sopenharmony_ci .d_type = ELF_T_WORD, 335da0c48c4Sopenharmony_ci .d_size = 8, 336da0c48c4Sopenharmony_ci .d_buf = (void *) desc 337da0c48c4Sopenharmony_ci }; 338da0c48c4Sopenharmony_ci Elf_Data out = 339da0c48c4Sopenharmony_ci { 340da0c48c4Sopenharmony_ci .d_version = EV_CURRENT, 341da0c48c4Sopenharmony_ci .d_type = ELF_T_WORD, 342da0c48c4Sopenharmony_ci .d_size = descsz, 343da0c48c4Sopenharmony_ci .d_buf = (void *) &prop 344da0c48c4Sopenharmony_ci }; 345da0c48c4Sopenharmony_ci 346da0c48c4Sopenharmony_ci if (gelf_xlatetom (ebl->elf, &out, &in, 347da0c48c4Sopenharmony_ci elf_getident (ebl->elf, 348da0c48c4Sopenharmony_ci NULL)[EI_DATA]) == NULL) 349da0c48c4Sopenharmony_ci { 350da0c48c4Sopenharmony_ci printf ("%s\n", elf_errmsg (-1)); 351da0c48c4Sopenharmony_ci return; 352da0c48c4Sopenharmony_ci } 353da0c48c4Sopenharmony_ci 354da0c48c4Sopenharmony_ci desc += 8; 355da0c48c4Sopenharmony_ci descsz -= 8; 356da0c48c4Sopenharmony_ci 357da0c48c4Sopenharmony_ci if (prop.pr_datasz > descsz) 358da0c48c4Sopenharmony_ci { 359da0c48c4Sopenharmony_ci printf ("BAD property datasz: %" PRId32 "\n", 360da0c48c4Sopenharmony_ci prop.pr_datasz); 361da0c48c4Sopenharmony_ci return; 362da0c48c4Sopenharmony_ci } 363da0c48c4Sopenharmony_ci 364da0c48c4Sopenharmony_ci int elfclass = gelf_getclass (ebl->elf); 365da0c48c4Sopenharmony_ci char *elfident = elf_getident (ebl->elf, NULL); 366da0c48c4Sopenharmony_ci GElf_Ehdr ehdr; 367da0c48c4Sopenharmony_ci gelf_getehdr (ebl->elf, &ehdr); 368da0c48c4Sopenharmony_ci 369da0c48c4Sopenharmony_ci /* Prefix. */ 370da0c48c4Sopenharmony_ci printf (" "); 371da0c48c4Sopenharmony_ci if (prop.pr_type == GNU_PROPERTY_STACK_SIZE) 372da0c48c4Sopenharmony_ci { 373da0c48c4Sopenharmony_ci printf ("STACK_SIZE "); 374da0c48c4Sopenharmony_ci union 375da0c48c4Sopenharmony_ci { 376da0c48c4Sopenharmony_ci Elf64_Addr a64; 377da0c48c4Sopenharmony_ci Elf32_Addr a32; 378da0c48c4Sopenharmony_ci } addr; 379da0c48c4Sopenharmony_ci if ((elfclass == ELFCLASS32 && prop.pr_datasz == 4) 380da0c48c4Sopenharmony_ci || (elfclass == ELFCLASS64 && prop.pr_datasz == 8)) 381da0c48c4Sopenharmony_ci { 382da0c48c4Sopenharmony_ci in.d_type = ELF_T_ADDR; 383da0c48c4Sopenharmony_ci out.d_type = ELF_T_ADDR; 384da0c48c4Sopenharmony_ci in.d_size = prop.pr_datasz; 385da0c48c4Sopenharmony_ci out.d_size = prop.pr_datasz; 386da0c48c4Sopenharmony_ci in.d_buf = (void *) desc; 387da0c48c4Sopenharmony_ci out.d_buf = (elfclass == ELFCLASS32 388da0c48c4Sopenharmony_ci ? (void *) &addr.a32 389da0c48c4Sopenharmony_ci : (void *) &addr.a64); 390da0c48c4Sopenharmony_ci 391da0c48c4Sopenharmony_ci if (gelf_xlatetom (ebl->elf, &out, &in, 392da0c48c4Sopenharmony_ci elfident[EI_DATA]) == NULL) 393da0c48c4Sopenharmony_ci { 394da0c48c4Sopenharmony_ci printf ("%s\n", elf_errmsg (-1)); 395da0c48c4Sopenharmony_ci return; 396da0c48c4Sopenharmony_ci } 397da0c48c4Sopenharmony_ci if (elfclass == ELFCLASS32) 398da0c48c4Sopenharmony_ci printf ("%#" PRIx32 "\n", addr.a32); 399da0c48c4Sopenharmony_ci else 400da0c48c4Sopenharmony_ci printf ("%#" PRIx64 "\n", addr.a64); 401da0c48c4Sopenharmony_ci } 402da0c48c4Sopenharmony_ci else 403da0c48c4Sopenharmony_ci printf (" (garbage datasz: %" PRIx32 ")\n", 404da0c48c4Sopenharmony_ci prop.pr_datasz); 405da0c48c4Sopenharmony_ci } 406da0c48c4Sopenharmony_ci else if (prop.pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED) 407da0c48c4Sopenharmony_ci { 408da0c48c4Sopenharmony_ci printf ("NO_COPY_ON_PROTECTION"); 409da0c48c4Sopenharmony_ci if (prop.pr_datasz == 0) 410da0c48c4Sopenharmony_ci printf ("\n"); 411da0c48c4Sopenharmony_ci else 412da0c48c4Sopenharmony_ci printf (" (garbage datasz: %" PRIx32 ")\n", 413da0c48c4Sopenharmony_ci prop.pr_datasz); 414da0c48c4Sopenharmony_ci } 415da0c48c4Sopenharmony_ci else if (prop.pr_type >= GNU_PROPERTY_LOPROC 416da0c48c4Sopenharmony_ci && prop.pr_type <= GNU_PROPERTY_HIPROC 417da0c48c4Sopenharmony_ci && (ehdr.e_machine == EM_386 418da0c48c4Sopenharmony_ci || ehdr.e_machine == EM_X86_64)) 419da0c48c4Sopenharmony_ci { 420da0c48c4Sopenharmony_ci printf ("X86 "); 421da0c48c4Sopenharmony_ci if (prop.pr_type == GNU_PROPERTY_X86_FEATURE_1_AND) 422da0c48c4Sopenharmony_ci { 423da0c48c4Sopenharmony_ci printf ("FEATURE_1_AND: "); 424da0c48c4Sopenharmony_ci 425da0c48c4Sopenharmony_ci if (prop.pr_datasz == 4) 426da0c48c4Sopenharmony_ci { 427da0c48c4Sopenharmony_ci GElf_Word data; 428da0c48c4Sopenharmony_ci in.d_type = ELF_T_WORD; 429da0c48c4Sopenharmony_ci out.d_type = ELF_T_WORD; 430da0c48c4Sopenharmony_ci in.d_size = 4; 431da0c48c4Sopenharmony_ci out.d_size = 4; 432da0c48c4Sopenharmony_ci in.d_buf = (void *) desc; 433da0c48c4Sopenharmony_ci out.d_buf = (void *) &data; 434da0c48c4Sopenharmony_ci 435da0c48c4Sopenharmony_ci if (gelf_xlatetom (ebl->elf, &out, &in, 436da0c48c4Sopenharmony_ci elfident[EI_DATA]) == NULL) 437da0c48c4Sopenharmony_ci { 438da0c48c4Sopenharmony_ci printf ("%s\n", elf_errmsg (-1)); 439da0c48c4Sopenharmony_ci return; 440da0c48c4Sopenharmony_ci } 441da0c48c4Sopenharmony_ci printf ("%08" PRIx32 " ", data); 442da0c48c4Sopenharmony_ci 443da0c48c4Sopenharmony_ci if ((data & GNU_PROPERTY_X86_FEATURE_1_IBT) 444da0c48c4Sopenharmony_ci != 0) 445da0c48c4Sopenharmony_ci { 446da0c48c4Sopenharmony_ci printf ("IBT"); 447da0c48c4Sopenharmony_ci data &= ~GNU_PROPERTY_X86_FEATURE_1_IBT; 448da0c48c4Sopenharmony_ci if (data != 0) 449da0c48c4Sopenharmony_ci printf (" "); 450da0c48c4Sopenharmony_ci } 451da0c48c4Sopenharmony_ci 452da0c48c4Sopenharmony_ci if ((data & GNU_PROPERTY_X86_FEATURE_1_SHSTK) 453da0c48c4Sopenharmony_ci != 0) 454da0c48c4Sopenharmony_ci { 455da0c48c4Sopenharmony_ci printf ("SHSTK"); 456da0c48c4Sopenharmony_ci data &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK; 457da0c48c4Sopenharmony_ci if (data != 0) 458da0c48c4Sopenharmony_ci printf (" "); 459da0c48c4Sopenharmony_ci } 460da0c48c4Sopenharmony_ci 461da0c48c4Sopenharmony_ci if (data != 0) 462da0c48c4Sopenharmony_ci printf ("UNKNOWN"); 463da0c48c4Sopenharmony_ci } 464da0c48c4Sopenharmony_ci else 465da0c48c4Sopenharmony_ci printf ("<bad datasz: %" PRId32 ">", 466da0c48c4Sopenharmony_ci prop.pr_datasz); 467da0c48c4Sopenharmony_ci 468da0c48c4Sopenharmony_ci printf ("\n"); 469da0c48c4Sopenharmony_ci } 470da0c48c4Sopenharmony_ci else 471da0c48c4Sopenharmony_ci { 472da0c48c4Sopenharmony_ci printf ("%#" PRIx32, prop.pr_type); 473da0c48c4Sopenharmony_ci if (prop.pr_datasz > 0) 474da0c48c4Sopenharmony_ci { 475da0c48c4Sopenharmony_ci printf (" data: "); 476da0c48c4Sopenharmony_ci size_t i; 477da0c48c4Sopenharmony_ci for (i = 0; i < prop.pr_datasz - 1; i++) 478da0c48c4Sopenharmony_ci printf ("%02" PRIx8 " ", (uint8_t) desc[i]); 479da0c48c4Sopenharmony_ci printf ("%02" PRIx8 "\n", (uint8_t) desc[i]); 480da0c48c4Sopenharmony_ci } 481da0c48c4Sopenharmony_ci } 482da0c48c4Sopenharmony_ci } 483da0c48c4Sopenharmony_ci else if (prop.pr_type >= GNU_PROPERTY_LOPROC 484da0c48c4Sopenharmony_ci && prop.pr_type <= GNU_PROPERTY_HIPROC 485da0c48c4Sopenharmony_ci && ehdr.e_machine == EM_AARCH64) 486da0c48c4Sopenharmony_ci { 487da0c48c4Sopenharmony_ci printf ("AARCH64 "); 488da0c48c4Sopenharmony_ci if (prop.pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) 489da0c48c4Sopenharmony_ci { 490da0c48c4Sopenharmony_ci printf ("FEATURE_1_AND: "); 491da0c48c4Sopenharmony_ci 492da0c48c4Sopenharmony_ci if (prop.pr_datasz == 4) 493da0c48c4Sopenharmony_ci { 494da0c48c4Sopenharmony_ci GElf_Word data; 495da0c48c4Sopenharmony_ci in.d_type = ELF_T_WORD; 496da0c48c4Sopenharmony_ci out.d_type = ELF_T_WORD; 497da0c48c4Sopenharmony_ci in.d_size = 4; 498da0c48c4Sopenharmony_ci out.d_size = 4; 499da0c48c4Sopenharmony_ci in.d_buf = (void *) desc; 500da0c48c4Sopenharmony_ci out.d_buf = (void *) &data; 501da0c48c4Sopenharmony_ci 502da0c48c4Sopenharmony_ci if (gelf_xlatetom (ebl->elf, &out, &in, 503da0c48c4Sopenharmony_ci elfident[EI_DATA]) == NULL) 504da0c48c4Sopenharmony_ci { 505da0c48c4Sopenharmony_ci printf ("%s\n", elf_errmsg (-1)); 506da0c48c4Sopenharmony_ci return; 507da0c48c4Sopenharmony_ci } 508da0c48c4Sopenharmony_ci printf ("%08" PRIx32 " ", data); 509da0c48c4Sopenharmony_ci 510da0c48c4Sopenharmony_ci if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) 511da0c48c4Sopenharmony_ci != 0) 512da0c48c4Sopenharmony_ci { 513da0c48c4Sopenharmony_ci printf ("BTI"); 514da0c48c4Sopenharmony_ci data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_BTI; 515da0c48c4Sopenharmony_ci if (data != 0) 516da0c48c4Sopenharmony_ci printf (" "); 517da0c48c4Sopenharmony_ci } 518da0c48c4Sopenharmony_ci 519da0c48c4Sopenharmony_ci if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_PAC) 520da0c48c4Sopenharmony_ci != 0) 521da0c48c4Sopenharmony_ci { 522da0c48c4Sopenharmony_ci printf ("PAC"); 523da0c48c4Sopenharmony_ci data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_PAC; 524da0c48c4Sopenharmony_ci if (data != 0) 525da0c48c4Sopenharmony_ci printf (" "); 526da0c48c4Sopenharmony_ci } 527da0c48c4Sopenharmony_ci 528da0c48c4Sopenharmony_ci if (data != 0) 529da0c48c4Sopenharmony_ci printf ("UNKNOWN"); 530da0c48c4Sopenharmony_ci } 531da0c48c4Sopenharmony_ci else 532da0c48c4Sopenharmony_ci printf ("<bad datasz: %" PRId32 ">", 533da0c48c4Sopenharmony_ci prop.pr_datasz); 534da0c48c4Sopenharmony_ci 535da0c48c4Sopenharmony_ci printf ("\n"); 536da0c48c4Sopenharmony_ci } 537da0c48c4Sopenharmony_ci else 538da0c48c4Sopenharmony_ci { 539da0c48c4Sopenharmony_ci printf ("%#" PRIx32, prop.pr_type); 540da0c48c4Sopenharmony_ci if (prop.pr_datasz > 0) 541da0c48c4Sopenharmony_ci { 542da0c48c4Sopenharmony_ci printf (" data: "); 543da0c48c4Sopenharmony_ci size_t i; 544da0c48c4Sopenharmony_ci for (i = 0; i < prop.pr_datasz - 1; i++) 545da0c48c4Sopenharmony_ci printf ("%02" PRIx8 " ", (uint8_t) desc[i]); 546da0c48c4Sopenharmony_ci printf ("%02" PRIx8 "\n", (uint8_t) desc[i]); 547da0c48c4Sopenharmony_ci } 548da0c48c4Sopenharmony_ci } 549da0c48c4Sopenharmony_ci } 550da0c48c4Sopenharmony_ci else 551da0c48c4Sopenharmony_ci { 552da0c48c4Sopenharmony_ci if (prop.pr_type >= GNU_PROPERTY_LOPROC 553da0c48c4Sopenharmony_ci && prop.pr_type <= GNU_PROPERTY_HIPROC) 554da0c48c4Sopenharmony_ci printf ("proc_type %#" PRIx32, prop.pr_type); 555da0c48c4Sopenharmony_ci else if (prop.pr_type >= GNU_PROPERTY_LOUSER 556da0c48c4Sopenharmony_ci && prop.pr_type <= GNU_PROPERTY_HIUSER) 557da0c48c4Sopenharmony_ci printf ("app_type %#" PRIx32, prop.pr_type); 558da0c48c4Sopenharmony_ci else 559da0c48c4Sopenharmony_ci printf ("unknown_type %#" PRIx32, prop.pr_type); 560da0c48c4Sopenharmony_ci 561da0c48c4Sopenharmony_ci if (prop.pr_datasz > 0) 562da0c48c4Sopenharmony_ci { 563da0c48c4Sopenharmony_ci printf (" data: "); 564da0c48c4Sopenharmony_ci size_t i; 565da0c48c4Sopenharmony_ci for (i = 0; i < prop.pr_datasz - 1; i++) 566da0c48c4Sopenharmony_ci printf ("%02" PRIx8 " ", (uint8_t) desc[i]); 567da0c48c4Sopenharmony_ci printf ("%02" PRIx8 "\n", (uint8_t) desc[i]); 568da0c48c4Sopenharmony_ci } 569da0c48c4Sopenharmony_ci } 570da0c48c4Sopenharmony_ci 571da0c48c4Sopenharmony_ci if (elfclass == ELFCLASS32) 572da0c48c4Sopenharmony_ci prop.pr_datasz = NOTE_ALIGN4 (prop.pr_datasz); 573da0c48c4Sopenharmony_ci else 574da0c48c4Sopenharmony_ci prop.pr_datasz = NOTE_ALIGN8 (prop.pr_datasz); 575da0c48c4Sopenharmony_ci 576da0c48c4Sopenharmony_ci desc += prop.pr_datasz; 577da0c48c4Sopenharmony_ci if (descsz > prop.pr_datasz) 578da0c48c4Sopenharmony_ci descsz -= prop.pr_datasz; 579da0c48c4Sopenharmony_ci else 580da0c48c4Sopenharmony_ci descsz = 0; 581da0c48c4Sopenharmony_ci } 582da0c48c4Sopenharmony_ci } 583da0c48c4Sopenharmony_ci break; 584da0c48c4Sopenharmony_ci 585da0c48c4Sopenharmony_ci case NT_GNU_ABI_TAG: 586da0c48c4Sopenharmony_ci if (descsz >= 8 && descsz % 4 == 0) 587da0c48c4Sopenharmony_ci { 588da0c48c4Sopenharmony_ci Elf_Data in = 589da0c48c4Sopenharmony_ci { 590da0c48c4Sopenharmony_ci .d_version = EV_CURRENT, 591da0c48c4Sopenharmony_ci .d_type = ELF_T_WORD, 592da0c48c4Sopenharmony_ci .d_size = descsz, 593da0c48c4Sopenharmony_ci .d_buf = (void *) desc 594da0c48c4Sopenharmony_ci }; 595da0c48c4Sopenharmony_ci /* Normally NT_GNU_ABI_TAG is just 4 words (16 bytes). If it 596da0c48c4Sopenharmony_ci is much (4*) larger dynamically allocate memory to convert. */ 597da0c48c4Sopenharmony_ci#define FIXED_TAG_BYTES 16 598da0c48c4Sopenharmony_ci uint32_t sbuf[FIXED_TAG_BYTES]; 599da0c48c4Sopenharmony_ci uint32_t *buf; 600da0c48c4Sopenharmony_ci if (unlikely (descsz / 4 > FIXED_TAG_BYTES)) 601da0c48c4Sopenharmony_ci { 602da0c48c4Sopenharmony_ci buf = malloc (descsz); 603da0c48c4Sopenharmony_ci if (unlikely (buf == NULL)) 604da0c48c4Sopenharmony_ci return; 605da0c48c4Sopenharmony_ci } 606da0c48c4Sopenharmony_ci else 607da0c48c4Sopenharmony_ci buf = sbuf; 608da0c48c4Sopenharmony_ci Elf_Data out = 609da0c48c4Sopenharmony_ci { 610da0c48c4Sopenharmony_ci .d_version = EV_CURRENT, 611da0c48c4Sopenharmony_ci .d_type = ELF_T_WORD, 612da0c48c4Sopenharmony_ci .d_size = descsz, 613da0c48c4Sopenharmony_ci .d_buf = buf 614da0c48c4Sopenharmony_ci }; 615da0c48c4Sopenharmony_ci 616da0c48c4Sopenharmony_ci if (elf32_xlatetom (&out, &in, ebl->data) != NULL) 617da0c48c4Sopenharmony_ci { 618da0c48c4Sopenharmony_ci const char *os; 619da0c48c4Sopenharmony_ci switch (buf[0]) 620da0c48c4Sopenharmony_ci { 621da0c48c4Sopenharmony_ci case ELF_NOTE_OS_LINUX: 622da0c48c4Sopenharmony_ci os = "Linux"; 623da0c48c4Sopenharmony_ci break; 624da0c48c4Sopenharmony_ci 625da0c48c4Sopenharmony_ci case ELF_NOTE_OS_GNU: 626da0c48c4Sopenharmony_ci os = "GNU"; 627da0c48c4Sopenharmony_ci break; 628da0c48c4Sopenharmony_ci 629da0c48c4Sopenharmony_ci case ELF_NOTE_OS_SOLARIS2: 630da0c48c4Sopenharmony_ci os = "Solaris"; 631da0c48c4Sopenharmony_ci break; 632da0c48c4Sopenharmony_ci 633da0c48c4Sopenharmony_ci case ELF_NOTE_OS_FREEBSD: 634da0c48c4Sopenharmony_ci os = "FreeBSD"; 635da0c48c4Sopenharmony_ci break; 636da0c48c4Sopenharmony_ci 637da0c48c4Sopenharmony_ci default: 638da0c48c4Sopenharmony_ci os = "???"; 639da0c48c4Sopenharmony_ci break; 640da0c48c4Sopenharmony_ci } 641da0c48c4Sopenharmony_ci 642da0c48c4Sopenharmony_ci printf (_(" OS: %s, ABI: "), os); 643da0c48c4Sopenharmony_ci for (size_t cnt = 1; cnt < descsz / 4; ++cnt) 644da0c48c4Sopenharmony_ci { 645da0c48c4Sopenharmony_ci if (cnt > 1) 646da0c48c4Sopenharmony_ci putchar_unlocked ('.'); 647da0c48c4Sopenharmony_ci printf ("%" PRIu32, buf[cnt]); 648da0c48c4Sopenharmony_ci } 649da0c48c4Sopenharmony_ci putchar_unlocked ('\n'); 650da0c48c4Sopenharmony_ci } 651da0c48c4Sopenharmony_ci if (descsz / 4 > FIXED_TAG_BYTES) 652da0c48c4Sopenharmony_ci free (buf); 653da0c48c4Sopenharmony_ci break; 654da0c48c4Sopenharmony_ci } 655da0c48c4Sopenharmony_ci FALLTHROUGH; 656da0c48c4Sopenharmony_ci 657da0c48c4Sopenharmony_ci default: 658da0c48c4Sopenharmony_ci /* Unknown type. */ 659da0c48c4Sopenharmony_ci break; 660da0c48c4Sopenharmony_ci } 661da0c48c4Sopenharmony_ci } 662da0c48c4Sopenharmony_ci} 663