1 #include <xen/compile.h>
2 #include <xen/init.h>
3 #include <xen/errno.h>
4 #include <xen/lib.h>
5 #include <xen/string.h>
6 #include <xen/types.h>
7 #include <xen/efi.h>
8 #include <xen/elf.h>
9 #include <xen/version.h>
10
11 #include <asm/cache.h>
12
xen_compile_date(void)13 const char *xen_compile_date(void)
14 {
15 return XEN_COMPILE_DATE;
16 }
17
xen_compile_time(void)18 const char *xen_compile_time(void)
19 {
20 return XEN_COMPILE_TIME;
21 }
22
xen_compile_by(void)23 const char *xen_compile_by(void)
24 {
25 return XEN_COMPILE_BY;
26 }
27
xen_compile_domain(void)28 const char *xen_compile_domain(void)
29 {
30 return XEN_COMPILE_DOMAIN;
31 }
32
xen_compile_host(void)33 const char *xen_compile_host(void)
34 {
35 return XEN_COMPILE_HOST;
36 }
37
xen_compiler(void)38 const char *xen_compiler(void)
39 {
40 return XEN_COMPILER;
41 }
42
xen_major_version(void)43 unsigned int xen_major_version(void)
44 {
45 return XEN_VERSION;
46 }
47
xen_minor_version(void)48 unsigned int xen_minor_version(void)
49 {
50 return XEN_SUBVERSION;
51 }
52
xen_extra_version(void)53 const char *xen_extra_version(void)
54 {
55 return XEN_EXTRAVERSION;
56 }
57
xen_changeset(void)58 const char *xen_changeset(void)
59 {
60 return XEN_CHANGESET;
61 }
62
xen_banner(void)63 const char *xen_banner(void)
64 {
65 return XEN_BANNER;
66 }
67
xen_deny(void)68 const char *xen_deny(void)
69 {
70 return "<denied>";
71 }
72
73 static const void *build_id_p __read_mostly;
74 static unsigned int build_id_len __read_mostly;
75
xen_build_id(const void ** p,unsigned int * len)76 int xen_build_id(const void **p, unsigned int *len)
77 {
78 if ( !build_id_len )
79 return -ENODATA;
80
81 *len = build_id_len;
82 *p = build_id_p;
83
84 return 0;
85 }
86
87 #ifdef BUILD_ID
88 /* Defined in linker script. */
89 extern const Elf_Note __note_gnu_build_id_start[], __note_gnu_build_id_end[];
90
xen_build_id_check(const Elf_Note * n,unsigned int n_sz,const void ** p,unsigned int * len)91 int xen_build_id_check(const Elf_Note *n, unsigned int n_sz,
92 const void **p, unsigned int *len)
93 {
94 /* Check if we really have a build-id. */
95 ASSERT(n_sz > sizeof(*n));
96
97 if ( NT_GNU_BUILD_ID != n->type )
98 return -ENODATA;
99
100 if ( n->namesz + n->descsz < n->namesz )
101 return -EINVAL;
102
103 if ( n->namesz < 4 /* GNU\0 */)
104 return -EINVAL;
105
106 if ( n->namesz + n->descsz > n_sz - sizeof(*n) )
107 return -EINVAL;
108
109 /* Sanity check, name should be "GNU" for ld-generated build-id. */
110 if ( strncmp(ELFNOTE_NAME(n), "GNU", n->namesz) != 0 )
111 return -ENODATA;
112
113 if ( len )
114 *len = n->descsz;
115 if ( p )
116 *p = ELFNOTE_DESC(n);
117
118 return 0;
119 }
120
121 struct pe_external_debug_directory
122 {
123 uint32_t characteristics;
124 uint32_t time_stamp;
125 uint16_t major_version;
126 uint16_t minor_version;
127 #define PE_IMAGE_DEBUG_TYPE_CODEVIEW 2
128 uint32_t type;
129 uint32_t size;
130 uint32_t rva_of_data;
131 uint32_t filepos_of_data;
132 };
133
134 struct cv_info_pdb70
135 {
136 #define CVINFO_PDB70_CVSIGNATURE 0x53445352 /* "RSDS" */
137 uint32_t cv_signature;
138 unsigned char signature[16];
139 uint32_t age;
140 char pdb_filename[];
141 };
142
xen_build_init(void)143 static int __init xen_build_init(void)
144 {
145 const Elf_Note *n = __note_gnu_build_id_start;
146 unsigned int sz;
147 int rc;
148
149 /* --build-id invoked with wrong parameters. */
150 if ( __note_gnu_build_id_end <= &n[0] )
151 return -ENODATA;
152
153 /* Check for full Note header. */
154 if ( &n[1] >= __note_gnu_build_id_end )
155 return -ENODATA;
156
157 sz = (void *)__note_gnu_build_id_end - (void *)n;
158
159 rc = xen_build_id_check(n, sz, &build_id_p, &build_id_len);
160
161 #ifdef CONFIG_X86
162 /* Alternatively we may have a CodeView record from an EFI build. */
163 if ( rc && efi_enabled(EFI_LOADER) )
164 {
165 const struct pe_external_debug_directory *dir = (const void *)n;
166
167 /*
168 * Validate that the full-note-header check above won't prevent
169 * fall-through to the CodeView case here.
170 */
171 BUILD_BUG_ON(sizeof(*n) > sizeof(*dir));
172
173 if ( sz > sizeof(*dir) + sizeof(struct cv_info_pdb70) &&
174 dir->type == PE_IMAGE_DEBUG_TYPE_CODEVIEW &&
175 dir->size > sizeof(struct cv_info_pdb70) &&
176 XEN_VIRT_START + dir->rva_of_data == (unsigned long)(dir + 1) )
177 {
178 const struct cv_info_pdb70 *info = (const void *)(dir + 1);
179
180 if ( info->cv_signature == CVINFO_PDB70_CVSIGNATURE )
181 {
182 build_id_p = info->signature;
183 build_id_len = sizeof(info->signature);
184 rc = 0;
185 }
186 }
187 }
188 #endif
189 if ( !rc )
190 printk(XENLOG_INFO "build-id: %*phN\n", build_id_len, build_id_p);
191
192 return rc;
193 }
194 __initcall(xen_build_init);
195 #endif
196 /*
197 * Local variables:
198 * mode: C
199 * c-file-style: "BSD"
200 * c-basic-offset: 4
201 * tab-width: 4
202 * indent-tabs-mode: nil
203 * End:
204 */
205