0
  +   ˆl–Ü4ý( ©³( 	Å€fàB¦-ÿÃ„iÇ ç_†I|¥�+ÃÂ ?÷     /* Simple code to turn various tables in an ELF file into alias definitions.
 * This deals with kernel datastructures where they should be
 * dealt with: in the kernel source.
 *
 * Copyright 2002-2003  Rusty Russell, IBM Corporation
 *           2003       Kai Germaschewski
 *
 *
 * This software may be used and distributed according to the terms
 * of the GNU General Public License, incorporated herein by reference.
 */

#include <stdarg.h>
#include <stdio.h>

#include "list.h"
#include "xalloc.h"

#include "modpost.h"
#include "devicetable-offsets.h"

/* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
 * use either stdint.h or inttypes.h for the rest. */
#if KERNEL_ELFCLASS == ELFCLASS32
typedef Elf32_Addr	kernel_ulong_t;
#define BITS_PER_LONG 32
#else
typedef Elf64_Addr	kernel_ulong_t;
#define BITS_PER_LONG 64
#endif
#ifdef __sun__
#include <inttypes.h>
#else
#include <stdint.h>
#endif

#include <ctype.h>
#include <stdbool.h>

/**
 * module_alias_printf - add auto-generated MODULE_ALIAS()
 *
 * @mod: module
 * @append_wildcard: append '*' for future extension if not exist yet
 * @fmt: printf(3)-like format
 */
static void __attribute__((format (printf, 3, 4)))
module_alias_printf(struct module *mod, bool append_wildcard,
		    const char *fmt, ...)
{
	struct module_alias *new;
	size_t len;
	int n;
	va_list ap;

	/* Determine required size. */
	va_start(ap, fmt);
	n = vsnprintf(NULL, 0, fmt, ap);
	va_end(ap);

	if (n < 0) {
		error("vsnprintf failed\n");
		return;
	}

	len = n + 1;	/* extra byte for '\0' */

	if (append_wildcard)
		len++;	/* extra byte for '*' */

	new = xmalloc(sizeof(*new) + len);

	/* Now, really print it to the allocated buffer */
	va_start(ap, fmt);
	n = vsnprintf(new->str, len, fmt, ap);
	va_end(ap);

	if (n < 0) {
		error("vsnprintf failed\n");
		free(new);
		return;
	}

	if (append_wildcard && (n == 0 || new->str[n - 1] != '*')) {
		new->str[n] = '*';
		new->str[n + 1] = '\0';
	}

	list_add_tail(&new->node, &mod->aliases);
}

typedef uint32_t	__u32;
typedef uint16_t	__u16;
typedef unsigned char	__u8;

/* UUID types for backward compatibility, don't use in new code */
typedef struct {
	__u8 b[16];
} guid_t;

typedef struct {
	__u8 b[16];
} uuid_t;

#define	UUID_STRING_LEN		36

/* MEI UUID type, don't use anywhere else */
typedef struct {
	__u8 b[16];
} uuid_le;

/* Big exception to the "don't include kernel headers into userspace, which
 * even potentially has different endianness and word sizes, since
 * we handle those differences explicitly below */
#include "../../include/linux/mod_devicetable.h"

/* This array collects all instances that use the generic do_table */
struct devtable {
	const char *device_id; /* name of table, __mod_<name>__*_device_table. */
	unsigned long id_size;
	void (*do_entry)(struct module *mod, void *symval);
};

/* Define a variable f that holds the value of field f of struct devid
 * based at address m.
 */
#define DEF_FIELD(m, devid, f) \
	typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f))

/* Define a variable v that holds the address of field f of struct devid
 * based at address m.  Due to the way typeof works, for a field of type
 * T[N] the variable has type T(*)[N], _not_ T*.
 */
#define DEF_FIELD_ADDR_VAR(m, devid, f, v) \
	typeof(((struct devid *)0)->f) *v = ((m) + OFF_##devid##_##f)

/* Define a variable f that holds the address of field f of struct devid
 * based at address m.  Due to the way typeof works, for a field of type
 * T[N] the variable has type T(*)[N], _not_ T*.
 */
#define DEF_FIELD_ADDR(m, devid, f) \
	DEF_FIELD_ADDR_VAR(m, devid, f, f)

#define ADD(str, sep, cond, field)                              \
do {                                                            \
        strcat(str, sep);                                       \
        if (cond)                                               \
                sprintf(str + strlen(str),                      \
                        sizeof(field) == 1 ? "%02X" :           \