ctf_loader: One more attempt at handling packed enums
With this a "make allyesconfig" on a 2.6.29-rc8 Linux kernel build left 16 cases flagged by ctfdwdiff, 8 unique ones, out of 6209 single-cu (compile unit) .o files. But what this clearly shows is that we really need to detect if a struct is packed, and wether it is naturally packed or if __attribute__ packed was used, that way we will have more clues as to if a enum is packed or if the whole struct where it is used as a type for a/several member(s) is packed. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
c1d567f047
commit
23df52c620
32
ctf_loader.c
32
ctf_loader.c
|
@ -800,24 +800,30 @@ static int class__fixup_ctf_bitfields(struct tag *self, struct cu *cu)
|
|||
pos->bitfield_size = 0;
|
||||
pos->byte_offset = pos->bit_offset / 8;
|
||||
|
||||
if (type->tag != DW_TAG_base_type &&
|
||||
!tag__is_enumeration(type)) {
|
||||
uint16_t type_bit_size;
|
||||
size_t integral_bit_size;
|
||||
|
||||
switch (type->tag) {
|
||||
case DW_TAG_enumeration_type:
|
||||
type_bit_size = tag__type(type)->size;
|
||||
/* Best we can do to check if this is a packed enum */
|
||||
if (is_power_of_2(type_bit_size))
|
||||
integral_bit_size = roundup(type_bit_size, 8);
|
||||
else
|
||||
integral_bit_size = sizeof(int) * 8;
|
||||
break;
|
||||
case DW_TAG_base_type: {
|
||||
struct base_type *bt = tag__base_type(type);
|
||||
type_bit_size = bt->bit_size;
|
||||
integral_bit_size = base_type__name_to_size(bt, cu);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pos->byte_size = tag__size(type, cu);
|
||||
pos->bit_size = pos->byte_size * 8;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t type_bit_size;
|
||||
size_t integral_bit_size;
|
||||
|
||||
if (tag__is_enumeration(type)) {
|
||||
type_bit_size = tag__type(type)->size;
|
||||
integral_bit_size = sizeof(int) * 8; /* FIXME: always this size? */
|
||||
} else {
|
||||
struct base_type *bt = tag__base_type(type);
|
||||
type_bit_size = bt->bit_size;
|
||||
integral_bit_size = base_type__name_to_size(bt, cu);
|
||||
}
|
||||
/*
|
||||
* XXX: integral_bit_size can be zero if base_type__name_to_size doesn't
|
||||
* know about the base_type name, so one has to add there when
|
||||
|
|
20
dutil.h
20
dutil.h
|
@ -1,12 +1,15 @@
|
|||
#ifndef _DUTIL_H_
|
||||
#define _DUTIL_H_ 1
|
||||
/*
|
||||
Copyright (C) 2007 Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of version 2 of the GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
*/
|
||||
* Copyright (C) 2007..2009 Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Some functions came from the Linux Kernel sources, copyrighted by a
|
||||
* cast of dozens, please see the Linux Kernel git history for details.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
@ -21,6 +24,11 @@
|
|||
|
||||
#define roundup(x,y) ((((x) + ((y) - 1)) / (y)) * (y))
|
||||
|
||||
static inline __attribute__((const)) bool is_power_of_2(unsigned long n)
|
||||
{
|
||||
return (n != 0 && ((n & (n - 1)) == 0));
|
||||
}
|
||||
|
||||
/* We need define two variables, argp_program_version_hook and
|
||||
argp_program_bug_address, in all programs. argp.h declares these
|
||||
variables as non-const (which is correct in general). But we can
|
||||
|
|
|
@ -41,7 +41,7 @@ static void emit_tag(struct tag *self, uint32_t tag_id, struct cu *cu)
|
|||
putchar('\n');
|
||||
lexblock__fprintf(&fn->lexblock, cu, fn, 0, stdout);
|
||||
}
|
||||
puts("\n");
|
||||
printf(" size: %zd\n\n", tag__size(self, cu));
|
||||
}
|
||||
|
||||
static int cu__emit_tags(struct cu *self, void *cookie __unused)
|
||||
|
|
Loading…
Reference in New Issue