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 void __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;
152 
153     /* Check for full Note header. */
154     if ( &n[1] >= __note_gnu_build_id_end )
155         return;
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 #endif
193 /*
194  * Local variables:
195  * mode: C
196  * c-file-style: "BSD"
197  * c-basic-offset: 4
198  * tab-width: 4
199  * indent-tabs-mode: nil
200  * End:
201  */
202