1 #include <xen/bug.h>
2 #include <xen/compile.h>
3 #include <xen/init.h>
4 #include <xen/errno.h>
5 #include <xen/lib.h>
6 #include <xen/sections.h>
7 #include <xen/string.h>
8 #include <xen/types.h>
9 #include <xen/efi.h>
10 #include <xen/elf.h>
11 #include <xen/version.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 char build_info[] =
74 "debug="
75 #ifdef CONFIG_DEBUG
76 "y"
77 #else
78 "n"
79 #endif
80 #ifdef CONFIG_COVERAGE
81 # ifdef __clang__
82 " llvmcov=y"
83 # else
84 " gcov=y"
85 # endif
86 #endif
87 #ifdef CONFIG_UBSAN
88 " ubsan=y"
89 #endif
90 "";
91
xen_build_info(void)92 const char *xen_build_info(void)
93 {
94 return build_info;
95 }
96
97 const void *__ro_after_init xen_build_id;
98 unsigned int __ro_after_init xen_build_id_len;
99
print_version(void)100 void print_version(void)
101 {
102 printk("Xen version %d.%d%s (%s@%s) (%s) %s %s\n",
103 xen_major_version(), xen_minor_version(), xen_extra_version(),
104 xen_compile_by(), xen_compile_domain(), xen_compiler(),
105 xen_build_info(), xen_compile_date());
106
107 printk("Latest ChangeSet: %s\n", xen_changeset());
108
109 if ( xen_build_id_len )
110 printk("build-id: %*phN\n", xen_build_id_len, xen_build_id);
111 }
112
113 #ifdef BUILD_ID
114 /* Defined in linker script. */
115 extern const Elf_Note __note_gnu_build_id_start[], __note_gnu_build_id_end[];
116
xen_build_id_check(const Elf_Note * n,unsigned int n_sz,const void ** p,unsigned int * len)117 int xen_build_id_check(const Elf_Note *n, unsigned int n_sz,
118 const void **p, unsigned int *len)
119 {
120 /* Check if we really have a build-id. */
121 ASSERT(n_sz > sizeof(*n));
122
123 if ( NT_GNU_BUILD_ID != n->type )
124 return -ENODATA;
125
126 if ( n->namesz + n->descsz < n->namesz )
127 return -EINVAL;
128
129 if ( n->namesz < 4 /* GNU\0 */)
130 return -EINVAL;
131
132 if ( n->namesz + n->descsz > n_sz - sizeof(*n) )
133 return -EINVAL;
134
135 /* Sanity check, name should be "GNU" for ld-generated build-id. */
136 if ( strncmp(ELFNOTE_NAME(n), "GNU", n->namesz) != 0 )
137 return -ENODATA;
138
139 if ( len )
140 *len = n->descsz;
141 if ( p )
142 *p = ELFNOTE_DESC(n);
143
144 return 0;
145 }
146
147 struct pe_external_debug_directory
148 {
149 uint32_t characteristics;
150 uint32_t time_stamp;
151 uint16_t major_version;
152 uint16_t minor_version;
153 #define PE_IMAGE_DEBUG_TYPE_CODEVIEW 2
154 uint32_t type;
155 uint32_t size;
156 uint32_t rva_of_data;
157 uint32_t filepos_of_data;
158 };
159
160 struct cv_info_pdb70
161 {
162 #define CVINFO_PDB70_CVSIGNATURE 0x53445352 /* "RSDS" */
163 uint32_t cv_signature;
164 unsigned char signature[16];
165 uint32_t age;
166 char pdb_filename[];
167 };
168
xen_build_init(void)169 void __init xen_build_init(void)
170 {
171 const Elf_Note *n = __note_gnu_build_id_start;
172 unsigned int sz;
173 int rc;
174
175 /* --build-id invoked with wrong parameters. */
176 if ( __note_gnu_build_id_end <= &n[0] )
177 return;
178
179 /* Check for full Note header. */
180 if ( &n[1] >= __note_gnu_build_id_end )
181 return;
182
183 sz = (uintptr_t)__note_gnu_build_id_end - (uintptr_t)n;
184
185 rc = xen_build_id_check(n, sz, &xen_build_id, &xen_build_id_len);
186
187 #ifdef CONFIG_X86
188 /*
189 * xen.efi built with a new enough toolchain will have a CodeView record,
190 * not an ELF note.
191 */
192 if ( rc )
193 {
194 const struct pe_external_debug_directory *dir = (const void *)n;
195
196 /*
197 * Validate that the full-note-header check above won't prevent
198 * fall-through to the CodeView case here.
199 */
200 BUILD_BUG_ON(sizeof(*n) > sizeof(*dir));
201
202 if ( sz > sizeof(*dir) + sizeof(struct cv_info_pdb70) &&
203 dir->type == PE_IMAGE_DEBUG_TYPE_CODEVIEW &&
204 dir->size > sizeof(struct cv_info_pdb70) &&
205 XEN_VIRT_START + dir->rva_of_data == (unsigned long)(dir + 1) )
206 {
207 const struct cv_info_pdb70 *info = (const void *)(dir + 1);
208
209 if ( info->cv_signature == CVINFO_PDB70_CVSIGNATURE )
210 {
211 xen_build_id = info->signature;
212 xen_build_id_len = sizeof(info->signature);
213 rc = 0;
214 }
215 }
216 }
217 #endif /* CONFIG_X86 */
218 }
219 #endif /* BUILD_ID */
220 /*
221 * Local variables:
222 * mode: C
223 * c-file-style: "BSD"
224 * c-basic-offset: 4
225 * tab-width: 4
226 * indent-tabs-mode: nil
227 * End:
228 */
229