d1fe8210cf1b79dc55cf4de465f66559683514ce
[platform/upstream/elfutils.git] / libebl / eblobjnote.c
1 /* Print contents of object file note.
2    Copyright (C) 2002, 2007, 2009, 2011 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5
6    This file is free software; you can redistribute it and/or modify
7    it under the terms of either
8
9      * the GNU Lesser General Public License as published by the Free
10        Software Foundation; either version 3 of the License, or (at
11        your option) any later version
12
13    or
14
15      * the GNU General Public License as published by the Free
16        Software Foundation; either version 2 of the License, or (at
17        your option) any later version
18
19    or both in parallel, as here.
20
21    elfutils is distributed in the hope that it will be useful, but
22    WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24    General Public License for more details.
25
26    You should have received copies of the GNU General Public License and
27    the GNU Lesser General Public License along with this program.  If
28    not, see <http://www.gnu.org/licenses/>.  */
29
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33
34 #include <inttypes.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <libeblP.h>
38
39
40 void
41 ebl_object_note (ebl, name, type, descsz, desc)
42      Ebl *ebl;
43      const char *name;
44      uint32_t type;
45      uint32_t descsz;
46      const char *desc;
47 {
48   if (! ebl->object_note (name, type, descsz, desc))
49     /* The machine specific function did not know this type.  */
50
51     if (strcmp ("stapsdt", name) == 0)
52       {
53         if (type != 3)
54           {
55             printf (gettext ("unknown SDT version %u\n"), type);
56             return;
57           }
58
59         /* Descriptor starts with three addresses, pc, base ref and
60            semaphore.  Then three zero terminated strings provider,
61            name and arguments.  */
62
63         union
64         {
65           Elf64_Addr a64[3];
66           Elf32_Addr a32[3];
67         } addrs;
68
69         size_t addrs_size = gelf_fsize (ebl->elf, ELF_T_ADDR, 3, EV_CURRENT);
70         if (descsz < addrs_size + 3)
71           {
72           invalid_sdt:
73             printf (gettext ("invalid SDT probe descriptor\n"));
74             return;
75           }
76
77         Elf_Data src =
78           {
79             .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
80             .d_buf = (void *) desc, .d_size = addrs_size
81           };
82
83         Elf_Data dst =
84           {
85             .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
86             .d_buf = &addrs, .d_size = addrs_size
87           };
88
89         if (gelf_xlatetom (ebl->elf, &dst, &src,
90                            elf_getident (ebl->elf, NULL)[EI_DATA]) == NULL)
91           {
92             printf ("%s\n", elf_errmsg (-1));
93             return;
94           }
95
96         const char *provider = desc + addrs_size;
97         const char *pname = memchr (provider, '\0', desc + descsz - provider);
98         if (pname == NULL)
99           goto invalid_sdt;
100
101         ++pname;
102         const char *args = memchr (pname, '\0', desc + descsz - pname);
103         if (args == NULL ||
104             memchr (++args, '\0', desc + descsz - pname) != desc + descsz - 1)
105           goto invalid_sdt;
106
107         GElf_Addr pc;
108         GElf_Addr base;
109         GElf_Addr sem;
110         if (gelf_getclass (ebl->elf) == ELFCLASS32)
111           {
112             pc = addrs.a32[0];
113             base = addrs.a32[1];
114             sem = addrs.a32[2];
115           }
116         else
117           {
118             pc = addrs.a64[0];
119             base = addrs.a64[1];
120             sem = addrs.a64[2];
121           }
122
123         printf (gettext ("    PC: "));
124         printf ("%#" PRIx64 ",", pc);
125         printf (gettext (" Base: "));
126         printf ("%#" PRIx64 ",", base);
127         printf (gettext (" Semaphore: "));
128         printf ("%#" PRIx64 "\n", sem);
129         printf (gettext ("    Provider: "));
130         printf ("%s,", provider);
131         printf (gettext (" Name: "));
132         printf ("%s,", pname);
133         printf (gettext (" Args: "));
134         printf ("'%s'\n", args);
135         return;
136       }
137
138     switch (type)
139       {
140       case NT_GNU_BUILD_ID:
141         if (strcmp (name, "GNU") == 0 && descsz > 0)
142           {
143             printf (gettext ("    Build ID: "));
144             uint_fast32_t i;
145             for (i = 0; i < descsz - 1; ++i)
146               printf ("%02" PRIx8, (uint8_t) desc[i]);
147             printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
148           }
149         break;
150
151       case NT_GNU_GOLD_VERSION:
152         if (strcmp (name, "GNU") == 0 && descsz > 0)
153           /* A non-null terminated version string.  */
154           printf (gettext ("    Linker version: %.*s\n"),
155                   (int) descsz, desc);
156         break;
157
158       case NT_GNU_ABI_TAG:
159         if (strcmp (name, "GNU") == 0 && descsz >= 8 && descsz % 4 == 0)
160           {
161             Elf_Data in =
162               {
163                 .d_version = EV_CURRENT,
164                 .d_type = ELF_T_WORD,
165                 .d_size = descsz,
166                 .d_buf = (void *) desc
167               };
168             uint32_t buf[descsz / 4];
169             Elf_Data out =
170               {
171                 .d_version = EV_CURRENT,
172                 .d_type = ELF_T_WORD,
173                 .d_size = descsz,
174                 .d_buf = buf
175               };
176
177             if (elf32_xlatetom (&out, &in, ebl->data) != NULL)
178               {
179                 const char *os;
180                 switch (buf[0])
181                   {
182                   case ELF_NOTE_OS_LINUX:
183                     os = "Linux";
184                     break;
185
186                   case ELF_NOTE_OS_GNU:
187                     os = "GNU";
188                     break;
189
190                   case ELF_NOTE_OS_SOLARIS2:
191                     os = "Solaris";
192                     break;
193
194                   case ELF_NOTE_OS_FREEBSD:
195                     os = "FreeBSD";
196                     break;
197
198                   default:
199                     os = "???";
200                     break;
201                   }
202
203                 printf (gettext ("    OS: %s, ABI: "), os);
204                 for (size_t cnt = 1; cnt < descsz / 4; ++cnt)
205                   {
206                     if (cnt > 1)
207                       putchar_unlocked ('.');
208                     printf ("%" PRIu32, buf[cnt]);
209                   }
210                 putchar_unlocked ('\n');
211               }
212             break;
213           }
214         /* FALLTHROUGH */
215
216       default:
217         /* Unknown type.  */
218         break;
219       }
220 }