blob: 1736e0f65208143843684c16ca832eadde5e25a8 [file] [log] [blame] [edit]
/* 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__ */