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