xref: /third_party/elfutils/libebl/eblobjnote.c (revision da0c48c4)
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