mirror of https://github.com/torvalds/linux.git
264 lines
7.0 KiB
C
264 lines
7.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* kabi_ex.h
|
|
*
|
|
* Copyright (C) 2024 Google LLC
|
|
*
|
|
* Examples for kABI stability features with --stable.
|
|
*/
|
|
|
|
/*
|
|
* The comments below each example contain the expected gendwarfksyms
|
|
* output, which can be verified using LLVM's FileCheck tool:
|
|
*
|
|
* https://llvm.org/docs/CommandGuide/FileCheck.html
|
|
*
|
|
* Usage:
|
|
*
|
|
* $ gcc -g -c examples/kabi_ex.c -o examples/kabi_ex.o
|
|
*
|
|
* $ nm examples/kabi_ex.o | awk '{ print $NF }' | \
|
|
* ./gendwarfksyms --stable --dump-dies \
|
|
* examples/kabi_ex.o 2>&1 >/dev/null | \
|
|
* FileCheck examples/kabi_ex.h --check-prefix=STABLE
|
|
*/
|
|
|
|
#ifndef __KABI_EX_H__
|
|
#define __KABI_EX_H__
|
|
|
|
#include "kabi.h"
|
|
|
|
/*
|
|
* Example: kABI rules
|
|
*/
|
|
|
|
struct s {
|
|
int a;
|
|
};
|
|
|
|
KABI_DECLONLY(s);
|
|
|
|
/*
|
|
* STABLE: variable structure_type s {
|
|
* STABLE-NEXT: }
|
|
*/
|
|
|
|
enum e {
|
|
A,
|
|
B,
|
|
C,
|
|
D,
|
|
};
|
|
|
|
KABI_ENUMERATOR_IGNORE(e, B);
|
|
KABI_ENUMERATOR_IGNORE(e, C);
|
|
KABI_ENUMERATOR_VALUE(e, D, 123456789);
|
|
|
|
/*
|
|
* STABLE: variable enumeration_type e {
|
|
* STABLE-NEXT: enumerator A = 0 ,
|
|
* STABLE-NEXT: enumerator D = 123456789
|
|
* STABLE-NEXT: } byte_size(4)
|
|
*/
|
|
|
|
/*
|
|
* Example: Reserved fields
|
|
*/
|
|
struct ex0a {
|
|
int a;
|
|
KABI_RESERVE(0);
|
|
KABI_RESERVE(1);
|
|
};
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex0a {
|
|
* STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) ,
|
|
* STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) data_member_location(8) ,
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16)
|
|
* STABLE-NEXT: } byte_size(24)
|
|
*/
|
|
|
|
struct ex0b {
|
|
int a;
|
|
KABI_RESERVE(0);
|
|
KABI_USE2(1, int b, int c);
|
|
};
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex0b {
|
|
* STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) ,
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(8) ,
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16)
|
|
* STABLE-NEXT: } byte_size(24)
|
|
*/
|
|
|
|
struct ex0c {
|
|
int a;
|
|
KABI_USE(0, void *p);
|
|
KABI_USE2(1, int b, int c);
|
|
};
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex0c {
|
|
* STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) ,
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(8) ,
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16)
|
|
* STABLE-NEXT: } byte_size(24)
|
|
*/
|
|
|
|
/*
|
|
* Example: A reserved array
|
|
*/
|
|
|
|
struct ex1a {
|
|
unsigned int a;
|
|
KABI_RESERVE_ARRAY(0, 64);
|
|
};
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex1a {
|
|
* STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) ,
|
|
* STABLE-NEXT: member array_type[64] {
|
|
* STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8)
|
|
* STABLE-NEXT: } data_member_location(8)
|
|
* STABLE-NEXT: } byte_size(72)
|
|
*/
|
|
|
|
struct ex1b {
|
|
unsigned int a;
|
|
KABI_USE_ARRAY(
|
|
0, 64, struct {
|
|
void *p;
|
|
KABI_RESERVE_ARRAY(1, 56);
|
|
});
|
|
};
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex1b {
|
|
* STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) ,
|
|
* STABLE-NEXT: member array_type[64] {
|
|
* STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8)
|
|
* STABLE-NEXT: } data_member_location(8)
|
|
* STABLE-NEXT: } byte_size(72)
|
|
*/
|
|
|
|
struct ex1c {
|
|
unsigned int a;
|
|
KABI_USE_ARRAY(0, 64, void *p[8]);
|
|
};
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex1c {
|
|
* STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) ,
|
|
* STABLE-NEXT: member array_type[64] {
|
|
* STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8)
|
|
* STABLE-NEXT: } data_member_location(8)
|
|
* STABLE-NEXT: } byte_size(72)
|
|
*/
|
|
|
|
/*
|
|
* Example: An ignored field added to an alignment hole
|
|
*/
|
|
|
|
struct ex2a {
|
|
int a;
|
|
unsigned long b;
|
|
int c;
|
|
unsigned long d;
|
|
};
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex2a {
|
|
* STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) ,
|
|
* STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) b data_member_location(8)
|
|
* STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) ,
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24)
|
|
* STABLE-NEXT: } byte_size(32)
|
|
*/
|
|
|
|
struct ex2b {
|
|
int a;
|
|
KABI_IGNORE(0, unsigned int n);
|
|
unsigned long b;
|
|
int c;
|
|
unsigned long d;
|
|
};
|
|
|
|
_Static_assert(sizeof(struct ex2a) == sizeof(struct ex2b), "ex2a size doesn't match ex2b");
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex2b {
|
|
* STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) ,
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8)
|
|
* STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) ,
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24)
|
|
* STABLE-NEXT: } byte_size(32)
|
|
*/
|
|
|
|
struct ex2c {
|
|
int a;
|
|
KABI_IGNORE(0, unsigned int n);
|
|
unsigned long b;
|
|
int c;
|
|
KABI_IGNORE(1, unsigned int m);
|
|
unsigned long d;
|
|
};
|
|
|
|
_Static_assert(sizeof(struct ex2a) == sizeof(struct ex2c), "ex2a size doesn't match ex2c");
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex2c {
|
|
* STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) ,
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8)
|
|
* STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) ,
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24)
|
|
* STABLE-NEXT: } byte_size(32)
|
|
*/
|
|
|
|
|
|
/*
|
|
* Example: A replaced field
|
|
*/
|
|
|
|
struct ex3a {
|
|
unsigned long a;
|
|
unsigned long unused;
|
|
};
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex3a {
|
|
* STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) a data_member_location(0)
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8)
|
|
* STABLE-NEXT: } byte_size(16)
|
|
*/
|
|
|
|
struct ex3b {
|
|
unsigned long a;
|
|
KABI_REPLACE(unsigned long, unused, unsigned long renamed);
|
|
};
|
|
|
|
_Static_assert(sizeof(struct ex3a) == sizeof(struct ex3b), "ex3a size doesn't match ex3b");
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex3b {
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0)
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8)
|
|
* STABLE-NEXT: } byte_size(16)
|
|
*/
|
|
|
|
struct ex3c {
|
|
unsigned long a;
|
|
KABI_REPLACE(unsigned long, unused, long replaced);
|
|
};
|
|
|
|
_Static_assert(sizeof(struct ex3a) == sizeof(struct ex3c), "ex3a size doesn't match ex3c");
|
|
|
|
/*
|
|
* STABLE: variable structure_type ex3c {
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0)
|
|
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8)
|
|
* STABLE-NEXT: } byte_size(16)
|
|
*/
|
|
|
|
#endif /* __KABI_EX_H__ */
|