Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/common/libelf/libelf-dominfo.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * parse xen-specific informations out of elf kernel binaries.
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation;
7
 * version 2.1 of the License.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
#include "libelf-private.h"
19
20
/* ------------------------------------------------------------------------ */
21
/* xen features                                                             */
22
23
static const char *const elf_xen_feature_names[] = {
24
    [XENFEAT_writable_page_tables] = "writable_page_tables",
25
    [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables",
26
    [XENFEAT_auto_translated_physmap] = "auto_translated_physmap",
27
    [XENFEAT_supervisor_mode_kernel] = "supervisor_mode_kernel",
28
    [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb",
29
    [XENFEAT_hvm_callback_vector] = "hvm_callback_vector",
30
    [XENFEAT_dom0] = "dom0"
31
};
32
static const unsigned elf_xen_features =
33
sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]);
34
35
elf_errorstatus elf_xen_parse_features(const char *features,
36
                           uint32_t *supported,
37
                           uint32_t *required)
38
1
{
39
1
    unsigned char feature[64];
40
1
    unsigned pos, len, i;
41
1
42
1
    if ( features == NULL )
43
0
        return 0;
44
1
45
5
    for ( pos = 0; features[pos] != '\0'; pos += len )
46
4
    {
47
4
        elf_memset_unchecked(feature, 0, sizeof(feature));
48
90
        for ( len = 0;; len++ )
49
94
        {
50
94
            if ( len >= sizeof(feature)-1 )
51
0
                break;
52
94
            if ( features[pos + len] == '\0' )
53
1
                break;
54
93
            if ( features[pos + len] == '|' )
55
3
            {
56
3
                len++;
57
3
                break;
58
3
            }
59
90
            feature[len] = features[pos + len];
60
90
        }
61
4
62
18
        for ( i = 0; i < elf_xen_features; i++ )
63
18
        {
64
18
            if ( !elf_xen_feature_names[i] )
65
3
                continue;
66
15
            if ( feature[0] == '!' )
67
0
            {
68
0
                /* required */
69
0
                if ( !strcmp(feature + 1, elf_xen_feature_names[i]) )
70
0
                {
71
0
                    elf_xen_feature_set(i, supported);
72
0
                    if ( required )
73
0
                        elf_xen_feature_set(i, required);
74
0
                    break;
75
0
                }
76
0
            }
77
15
            else
78
15
            {
79
15
                /* supported */
80
15
                if ( !strcmp(feature, elf_xen_feature_names[i]) )
81
4
                {
82
4
                    elf_xen_feature_set(i, supported);
83
4
                    break;
84
4
                }
85
15
            }
86
15
        }
87
4
        if ( i == elf_xen_features && required && feature[0] == '!' )
88
0
            return -1;
89
4
    }
90
1
91
1
    return 0;
92
1
}
93
94
/* ------------------------------------------------------------------------ */
95
/* xen elf notes                                                            */
96
97
elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
98
                       struct elf_dom_parms *parms,
99
                       ELF_HANDLE_DECL(elf_note) note)
100
15
{
101
15
/* *INDENT-OFF* */
102
15
    static const struct {
103
15
        char *name;
104
15
        bool str;
105
15
    } note_desc[] = {
106
15
        [XEN_ELFNOTE_ENTRY] = { "ENTRY", 0},
107
15
        [XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0},
108
15
        [XEN_ELFNOTE_VIRT_BASE] = { "VIRT_BASE", 0},
109
15
        [XEN_ELFNOTE_INIT_P2M] = { "INIT_P2M", 0},
110
15
        [XEN_ELFNOTE_PADDR_OFFSET] = { "PADDR_OFFSET", 0},
111
15
        [XEN_ELFNOTE_HV_START_LOW] = { "HV_START_LOW", 0},
112
15
        [XEN_ELFNOTE_XEN_VERSION] = { "XEN_VERSION", 1},
113
15
        [XEN_ELFNOTE_GUEST_OS] = { "GUEST_OS", 1},
114
15
        [XEN_ELFNOTE_GUEST_VERSION] = { "GUEST_VERSION", 1},
115
15
        [XEN_ELFNOTE_LOADER] = { "LOADER", 1},
116
15
        [XEN_ELFNOTE_PAE_MODE] = { "PAE_MODE", 1},
117
15
        [XEN_ELFNOTE_FEATURES] = { "FEATURES", 1},
118
15
        [XEN_ELFNOTE_SUPPORTED_FEATURES] = { "SUPPORTED_FEATURES", 0},
119
15
        [XEN_ELFNOTE_BSD_SYMTAB] = { "BSD_SYMTAB", 1},
120
15
        [XEN_ELFNOTE_SUSPEND_CANCEL] = { "SUSPEND_CANCEL", 0 },
121
15
        [XEN_ELFNOTE_MOD_START_PFN] = { "MOD_START_PFN", 0 },
122
15
        [XEN_ELFNOTE_PHYS32_ENTRY] = { "PHYS32_ENTRY", 0 },
123
15
    };
124
15
/* *INDENT-ON* */
125
15
126
15
    const char *str = NULL;
127
15
    uint64_t val = 0;
128
15
    unsigned int i;
129
15
    unsigned type = elf_uval(elf, note, type);
130
15
131
15
    if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) ||
132
15
         (note_desc[type].name == NULL) )
133
1
    {
134
1
        elf_msg(elf, "ELF: note: unknown (%#x)\n", type);
135
1
        return 0;
136
1
    }
137
15
138
14
    if ( note_desc[type].str )
139
7
    {
140
7
        str = elf_strval(elf, elf_note_desc(elf, note));
141
7
        if (str == NULL)
142
7
            /* elf_strval will mark elf broken if it fails so no need to log */
143
0
            return 0;
144
7
        elf_msg(elf, "ELF: note: %s = \"%s\"\n", note_desc[type].name, str);
145
7
        parms->elf_notes[type].type = XEN_ENT_STR;
146
7
        parms->elf_notes[type].data.str = str;
147
7
    }
148
14
    else
149
7
    {
150
7
        val = elf_note_numeric(elf, note);
151
7
        elf_msg(elf, "ELF: note: %s = %#" PRIx64 "\n", note_desc[type].name, val);
152
7
        parms->elf_notes[type].type = XEN_ENT_LONG;
153
7
        parms->elf_notes[type].data.num = val;
154
7
    }
155
14
    parms->elf_notes[type].name = note_desc[type].name;
156
14
157
14
    switch ( type )
158
14
    {
159
1
    case XEN_ELFNOTE_LOADER:
160
1
        safe_strcpy(parms->loader, str);
161
1
        break;
162
1
    case XEN_ELFNOTE_GUEST_OS:
163
1
        safe_strcpy(parms->guest_os, str);
164
1
        break;
165
1
    case XEN_ELFNOTE_GUEST_VERSION:
166
1
        safe_strcpy(parms->guest_ver, str);
167
1
        break;
168
1
    case XEN_ELFNOTE_XEN_VERSION:
169
1
        safe_strcpy(parms->xen_ver, str);
170
1
        break;
171
1
    case XEN_ELFNOTE_PAE_MODE:
172
1
        if ( !strcmp(str, "yes") )
173
1
            parms->pae = XEN_PAE_EXTCR3;
174
1
        if ( strstr(str, "bimodal") )
175
0
            parms->pae = XEN_PAE_BIMODAL;
176
1
        break;
177
1
    case XEN_ELFNOTE_BSD_SYMTAB:
178
1
        if ( !strcmp(str, "yes") )
179
1
            parms->bsd_symtab = 1;
180
1
        break;
181
1
182
1
    case XEN_ELFNOTE_VIRT_BASE:
183
1
        parms->virt_base = val;
184
1
        break;
185
1
    case XEN_ELFNOTE_ENTRY:
186
1
        parms->virt_entry = val;
187
1
        break;
188
0
    case XEN_ELFNOTE_INIT_P2M:
189
0
        parms->p2m_base = val;
190
0
        break;
191
0
    case XEN_ELFNOTE_MOD_START_PFN:
192
0
        parms->unmapped_initrd = !!val;
193
0
        break;
194
1
    case XEN_ELFNOTE_PADDR_OFFSET:
195
1
        parms->elf_paddr_offset = val;
196
1
        break;
197
1
    case XEN_ELFNOTE_HYPERCALL_PAGE:
198
1
        parms->virt_hypercall = val;
199
1
        break;
200
1
    case XEN_ELFNOTE_HV_START_LOW:
201
1
        parms->virt_hv_start_low = val;
202
1
        break;
203
1
204
1
    case XEN_ELFNOTE_FEATURES:
205
1
        if ( elf_xen_parse_features(str, parms->f_supported,
206
1
                                    parms->f_required) )
207
0
            return -1;
208
1
        break;
209
1
210
0
    case XEN_ELFNOTE_SUPPORTED_FEATURES:
211
0
        for ( i = 0; i < XENFEAT_NR_SUBMAPS; ++i )
212
0
            parms->f_supported[i] |= elf_note_numeric_array(
213
0
                elf, note, sizeof(*parms->f_supported), i);
214
0
        break;
215
1
216
1
    case XEN_ELFNOTE_PHYS32_ENTRY:
217
1
        parms->phys_entry = val;
218
1
        break;
219
14
    }
220
14
    return 0;
221
14
}
222
223
1
#define ELF_NOTE_INVALID (~0U)
224
225
static unsigned elf_xen_parse_notes(struct elf_binary *elf,
226
                               struct elf_dom_parms *parms,
227
                               elf_ptrval start,
228
                               elf_ptrval end,
229
                               unsigned *total_note_count)
230
1
{
231
1
    unsigned xen_elfnotes = 0;
232
1
    ELF_HANDLE_DECL(elf_note) note;
233
1
    const char *note_name;
234
1
235
1
    parms->elf_note_start = start;
236
1
    parms->elf_note_end   = end;
237
1
    for ( note = ELF_MAKE_HANDLE(elf_note, parms->elf_note_start);
238
16
          ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
239
15
          note = elf_note_next(elf, note) )
240
15
    {
241
15
#ifdef __XEN__
242
15
        process_pending_softirqs();
243
15
#endif
244
15
245
15
        if ( *total_note_count >= ELF_MAX_TOTAL_NOTE_COUNT )
246
0
        {
247
0
            elf_mark_broken(elf, "too many ELF notes");
248
0
            break;
249
0
        }
250
15
        (*total_note_count)++;
251
15
        note_name = elf_note_name(elf, note);
252
15
        if ( note_name == NULL )
253
0
            continue;
254
15
        if ( strcmp(note_name, "Xen") )
255
0
            continue;
256
15
        if ( elf_xen_parse_note(elf, parms, note) )
257
0
            return ELF_NOTE_INVALID;
258
15
        xen_elfnotes++;
259
15
    }
260
1
    return xen_elfnotes;
261
1
}
262
263
/* ------------------------------------------------------------------------ */
264
/* __xen_guest section                                                      */
265
266
elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
267
                             struct elf_dom_parms *parms)
268
0
{
269
0
    elf_ptrval h;
270
0
    unsigned char name[32], value[128];
271
0
    unsigned len;
272
0
273
0
    h = parms->guest_info;
274
0
#define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
275
0
    while ( STAR(h) )
276
0
    {
277
0
        elf_memset_unchecked(name, 0, sizeof(name));
278
0
        elf_memset_unchecked(value, 0, sizeof(value));
279
0
        for ( len = 0;; len++, h++ )
280
0
        {
281
0
            if ( len >= sizeof(name)-1 )
282
0
                break;
283
0
            if ( STAR(h) == '\0' )
284
0
                break;
285
0
            if ( STAR(h) == ',' )
286
0
            {
287
0
                h++;
288
0
                break;
289
0
            }
290
0
            if ( STAR(h) == '=' )
291
0
            {
292
0
                h++;
293
0
                for ( len = 0;; len++, h++ )
294
0
                {
295
0
                    if ( len >= sizeof(value)-1 )
296
0
                        break;
297
0
                    if ( STAR(h) == '\0' )
298
0
                        break;
299
0
                    if ( STAR(h) == ',' )
300
0
                    {
301
0
                        h++;
302
0
                        break;
303
0
                    }
304
0
                    value[len] = STAR(h);
305
0
                }
306
0
                break;
307
0
            }
308
0
            name[len] = STAR(h);
309
0
        }
310
0
        elf_msg(elf, "ELF: %s=\"%s\"\n", name, value);
311
0
312
0
        /* strings */
313
0
        if ( !strcmp(name, "LOADER") )
314
0
            safe_strcpy(parms->loader, value);
315
0
        if ( !strcmp(name, "GUEST_OS") )
316
0
            safe_strcpy(parms->guest_os, value);
317
0
        if ( !strcmp(name, "GUEST_VER") )
318
0
            safe_strcpy(parms->guest_ver, value);
319
0
        if ( !strcmp(name, "XEN_VER") )
320
0
            safe_strcpy(parms->xen_ver, value);
321
0
        if ( !strcmp(name, "PAE") )
322
0
        {
323
0
            if ( !strcmp(value, "yes[extended-cr3]") )
324
0
                parms->pae = XEN_PAE_EXTCR3;
325
0
            else if ( !strncmp(value, "yes", 3) )
326
0
                parms->pae = XEN_PAE_YES;
327
0
        }
328
0
        if ( !strcmp(name, "BSD_SYMTAB") )
329
0
            parms->bsd_symtab = 1;
330
0
331
0
        /* longs */
332
0
        if ( !strcmp(name, "VIRT_BASE") )
333
0
            parms->virt_base = strtoull(value, NULL, 0);
334
0
        if ( !strcmp(name, "VIRT_ENTRY") )
335
0
            parms->virt_entry = strtoull(value, NULL, 0);
336
0
        if ( !strcmp(name, "ELF_PADDR_OFFSET") )
337
0
            parms->elf_paddr_offset = strtoull(value, NULL, 0);
338
0
        if ( !strcmp(name, "HYPERCALL_PAGE") )
339
0
            parms->virt_hypercall = (strtoull(value, NULL, 0) << 12) +
340
0
                parms->virt_base;
341
0
342
0
        /* other */
343
0
        if ( !strcmp(name, "FEATURES") )
344
0
            if ( elf_xen_parse_features(value, parms->f_supported,
345
0
                                        parms->f_required) )
346
0
                return -1;
347
0
    }
348
0
    return 0;
349
0
}
350
351
/* ------------------------------------------------------------------------ */
352
/* sanity checks                                                            */
353
354
static elf_errorstatus elf_xen_note_check(struct elf_binary *elf,
355
                              struct elf_dom_parms *parms)
356
1
{
357
1
    if ( (ELF_PTRVAL_INVALID(parms->elf_note_start)) &&
358
0
         (ELF_PTRVAL_INVALID(parms->guest_info)) )
359
0
    {
360
0
        unsigned machine = elf_uval(elf, elf->ehdr, e_machine);
361
0
        if ( (machine == EM_386) || (machine == EM_X86_64) )
362
0
        {
363
0
            elf_err(elf, "ERROR: Not a Xen-ELF image: "
364
0
                    "No ELF notes or '__xen_guest' section found\n");
365
0
            return -1;
366
0
        }
367
0
        return 0;
368
0
    }
369
1
370
1
    if ( elf_uval(elf, elf->ehdr, e_machine) == EM_ARM )
371
0
    {
372
0
         elf_msg(elf, "ELF: Not bothering with notes on ARM\n");
373
0
         return 0;
374
0
    }
375
1
376
1
    /* Check the contents of the Xen notes or guest string. */
377
1
    if ( ((strlen(parms->loader) == 0) ||
378
1
          strncmp(parms->loader, "generic", 7)) &&
379
0
         ((strlen(parms->guest_os) == 0) ||
380
0
          strncmp(parms->guest_os, "linux", 5)) )
381
0
    {
382
0
        elf_err(elf,
383
0
                "ERROR: Will only load images built for the generic loader or Linux images"
384
0
                " (Not '%.*s' and '%.*s')\n",
385
0
                (int)sizeof(parms->loader), parms->loader,
386
0
                (int)sizeof(parms->guest_os), parms->guest_os);
387
0
        return -1;
388
0
    }
389
1
390
1
    if ( (strlen(parms->xen_ver) == 0) ||
391
1
         strncmp(parms->xen_ver, "xen-3.0", 7) )
392
0
    {
393
0
        elf_err(elf, "ERROR: Xen will only load images built for Xen v3.0 "
394
0
                "(Not '%.*s')\n",
395
0
                (int)sizeof(parms->xen_ver), parms->xen_ver);
396
0
        return -1;
397
0
    }
398
1
    return 0;
399
1
}
400
401
static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
402
                                   struct elf_dom_parms *parms)
403
1
{
404
1
    uint64_t virt_offset;
405
1
406
1
    if ( (parms->elf_paddr_offset != UNSET_ADDR) &&
407
1
         (parms->virt_base == UNSET_ADDR) )
408
0
    {
409
0
        elf_err(elf, "ERROR: ELF_PADDR_OFFSET set, VIRT_BASE unset\n");
410
0
        return -1;
411
0
    }
412
1
413
1
    /* Initial guess for virt_base is 0 if it is not explicitly defined. */
414
1
    if ( parms->virt_base == UNSET_ADDR )
415
0
    {
416
0
        parms->virt_base = 0;
417
0
        elf_msg(elf, "ELF: VIRT_BASE unset, using %#" PRIx64 "\n",
418
0
                parms->virt_base);
419
0
    }
420
1
421
1
    /*
422
1
     * If we are using the legacy __xen_guest section then elf_pa_off
423
1
     * defaults to v_start in order to maintain compatibility with
424
1
     * older hypervisors which set padd in the ELF header to
425
1
     * virt_base.
426
1
     *
427
1
     * If we are using the modern ELF notes interface then the default
428
1
     * is 0.
429
1
     */
430
1
    if ( parms->elf_paddr_offset == UNSET_ADDR )
431
0
    {
432
0
        if ( parms->elf_note_start )
433
0
            parms->elf_paddr_offset = 0;
434
0
        else
435
0
            parms->elf_paddr_offset = parms->virt_base;
436
0
        elf_msg(elf, "ELF_PADDR_OFFSET unset, using %#" PRIx64 "\n",
437
0
                parms->elf_paddr_offset);
438
0
    }
439
1
440
1
    virt_offset = parms->virt_base - parms->elf_paddr_offset;
441
1
    parms->virt_kstart = elf->pstart + virt_offset;
442
1
    parms->virt_kend   = elf->pend   + virt_offset;
443
1
444
1
    if ( parms->virt_entry == UNSET_ADDR )
445
0
        parms->virt_entry = elf_uval(elf, elf->ehdr, e_entry);
446
1
447
1
    if ( parms->bsd_symtab )
448
1
    {
449
1
        elf_parse_bsdsyms(elf, elf->pend);
450
1
        if ( elf->bsd_symtab_pend )
451
1
            parms->virt_kend = elf->bsd_symtab_pend + virt_offset;
452
1
    }
453
1
454
1
    elf_msg(elf, "ELF: addresses:\n");
455
1
    elf_msg(elf, "    virt_base        = 0x%" PRIx64 "\n", parms->virt_base);
456
1
    elf_msg(elf, "    elf_paddr_offset = 0x%" PRIx64 "\n", parms->elf_paddr_offset);
457
1
    elf_msg(elf, "    virt_offset      = 0x%" PRIx64 "\n", virt_offset);
458
1
    elf_msg(elf, "    virt_kstart      = 0x%" PRIx64 "\n", parms->virt_kstart);
459
1
    elf_msg(elf, "    virt_kend        = 0x%" PRIx64 "\n", parms->virt_kend);
460
1
    elf_msg(elf, "    virt_entry       = 0x%" PRIx64 "\n", parms->virt_entry);
461
1
    elf_msg(elf, "    p2m_base         = 0x%" PRIx64 "\n", parms->p2m_base);
462
1
463
1
    if ( (parms->virt_kstart > parms->virt_kend) ||
464
1
         (parms->virt_entry < parms->virt_kstart) ||
465
1
         (parms->virt_entry > parms->virt_kend) ||
466
1
         (parms->virt_base > parms->virt_kstart) )
467
0
    {
468
0
        elf_err(elf, "ERROR: ELF start or entries are out of bounds\n");
469
0
        return -1;
470
0
    }
471
1
472
1
    if ( (parms->p2m_base != UNSET_ADDR) &&
473
0
         (parms->p2m_base >= parms->virt_kstart) &&
474
0
         (parms->p2m_base < parms->virt_kend) )
475
0
    {
476
0
        elf_err(elf, "ERROR: P->M table base is out of bounds\n");
477
0
        return -1;
478
0
    }
479
1
480
1
    return 0;
481
1
}
482
483
/* ------------------------------------------------------------------------ */
484
/* glue it all together ...                                                 */
485
486
elf_errorstatus elf_xen_parse(struct elf_binary *elf,
487
                  struct elf_dom_parms *parms)
488
1
{
489
1
    ELF_HANDLE_DECL(elf_shdr) shdr;
490
1
    ELF_HANDLE_DECL(elf_phdr) phdr;
491
1
    unsigned xen_elfnotes = 0;
492
1
    unsigned i, count, more_notes;
493
1
    unsigned total_note_count = 0;
494
1
495
1
    elf_memset_unchecked(parms, 0, sizeof(*parms));
496
1
    parms->virt_base = UNSET_ADDR;
497
1
    parms->virt_entry = UNSET_ADDR;
498
1
    parms->virt_hypercall = UNSET_ADDR;
499
1
    parms->virt_hv_start_low = UNSET_ADDR;
500
1
    parms->p2m_base = UNSET_ADDR;
501
1
    parms->elf_paddr_offset = UNSET_ADDR;
502
1
    parms->phys_entry = UNSET_ADDR32;
503
1
504
1
    /* Find and parse elf notes. */
505
1
    count = elf_phdr_count(elf);
506
7
    for ( i = 0; i < count; i++ )
507
6
    {
508
6
        phdr = elf_phdr_by_index(elf, i);
509
6
        if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
510
6
            /* input has an insane program header count field */
511
0
            break;
512
6
        if ( elf_uval(elf, phdr, p_type) != PT_NOTE )
513
6
            continue;
514
6
515
6
        /*
516
6
         * Some versions of binutils do not correctly set p_offset for
517
6
         * note segments.
518
6
         */
519
0
        if (elf_uval(elf, phdr, p_offset) == 0)
520
0
             continue;
521
0
522
0
        more_notes = elf_xen_parse_notes(elf, parms,
523
0
                                 elf_segment_start(elf, phdr),
524
0
                                 elf_segment_end(elf, phdr),
525
0
                                 &total_note_count);
526
0
        if ( more_notes == ELF_NOTE_INVALID )
527
0
            return -1;
528
0
529
0
        xen_elfnotes += more_notes;
530
0
    }
531
1
532
1
    /*
533
1
     * Fall back to any SHT_NOTE sections if no valid note segments
534
1
     * were found.
535
1
     */
536
1
    if ( xen_elfnotes == 0 )
537
1
    {
538
1
        count = elf_shdr_count(elf);
539
50
        for ( i = 1; i < count; i++ )
540
49
        {
541
49
            shdr = elf_shdr_by_index(elf, i);
542
49
            if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
543
49
                /* input has an insane section header count field */
544
0
                break;
545
49
546
49
            if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
547
48
                continue;
548
49
549
1
            more_notes = elf_xen_parse_notes(elf, parms,
550
1
                                     elf_section_start(elf, shdr),
551
1
                                     elf_section_end(elf, shdr),
552
1
                                     &total_note_count);
553
1
554
1
            if ( more_notes == ELF_NOTE_INVALID )
555
0
                return -1;
556
1
557
1
            if ( xen_elfnotes == 0 && more_notes > 0 )
558
1
                elf_msg(elf, "ELF: using notes from SHT_NOTE section\n");
559
1
560
1
            xen_elfnotes += more_notes;
561
1
        }
562
1
563
1
    }
564
1
565
1
    /*
566
1
     * Finally fall back to the __xen_guest section.
567
1
     */
568
1
    if ( xen_elfnotes == 0 )
569
0
    {
570
0
        shdr = elf_shdr_by_name(elf, "__xen_guest");
571
0
        if ( ELF_HANDLE_VALID(shdr) )
572
0
        {
573
0
            parms->guest_info = elf_section_start(elf, shdr);
574
0
            parms->elf_note_start = ELF_INVALID_PTRVAL;
575
0
            parms->elf_note_end   = ELF_INVALID_PTRVAL;
576
0
            elf_msg(elf, "ELF: __xen_guest: \"%s\"\n",
577
0
                    elf_strfmt(elf, parms->guest_info));
578
0
            elf_xen_parse_guest_info(elf, parms);
579
0
        }
580
0
    }
581
1
582
1
    if ( elf_xen_note_check(elf, parms) != 0 )
583
0
        return -1;
584
1
    if ( elf_xen_addr_calc_check(elf, parms) != 0 )
585
0
        return -1;
586
1
    return 0;
587
1
}
588
589
/*
590
 * Local variables:
591
 * mode: C
592
 * c-file-style: "BSD"
593
 * c-basic-offset: 4
594
 * tab-width: 4
595
 * indent-tabs-mode: nil
596
 * End:
597
 */