Skip to content

Commit

Permalink
[RFC][BPF] Handle DW_TAG_atomic_type properly
Browse files Browse the repository at this point in the history
Make change in BTFDebug.cpp to handle DW_TAG_atomic_type properly.
Otherwise, a type like
   _Atomic int i; // global
the dwarf type chain atomic->int
Since DW_TAG_atomic_type is not processed BTF generation will stop
at atomic modifier and BTF will encode 'i' as void type.

Similar for type like
  volatile _Atomic int *p;
the dwarf type chain ptr->volatile->atomic->int
Since atomic type is not processed and BTF generation will stop at
atomic type, the eventual BTF type will be
  ptr->volatile->void
which is incorrect.

This patch fixed the above two patterns by skipping
DW_TAG_atomic_type. There could be more cases which I will try
to fix those with more test cases. This is a RFC patch and the
current implementation is good enough to run kernel selftests
with _Atomic usage ([1]).

In kernel selftest arena_atomics.c, the new bpf code looks like

```
_Atomic __u64 __arena_global and64_value = (0x110ull << 32);
_Atomic __u32 __arena_global and32_value = 0x110;

SEC("raw_tp/sys_enter")
int and(const void *ctx)
{
	...
        __c11_atomic_fetch_and(&and64_value, 0x011ull << 32, memory_order_relaxed);
        __c11_atomic_fetch_and(&and32_value, 0x011, memory_order_relaxed);
	...

        return 0;
}
```

The skel file arena_atomics.skel.h has
```
struct arena_atomics__arena {
	...
	__u64 and64_value;
	__u32 and32_value;
	...
} *arena;
```

  [1] https://lore.kernel.org/bpf/[email protected]/
  • Loading branch information
Yonghong Song committed Sep 9, 2024
1 parent bcca7b6 commit 8b82c54
Showing 1 changed file with 19 additions and 2 deletions.
21 changes: 19 additions & 2 deletions llvm/lib/Target/BPF/BTFDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ void BTFTypeDerived::completeType(BTFDebug &BDebug) {

// The base type for PTR/CONST/VOLATILE could be void.
const DIType *ResolvedType = DTy->getBaseType();
if (ResolvedType) {
const auto *DerivedTy = dyn_cast<DIDerivedType>(ResolvedType);
if (DerivedTy && DerivedTy->getTag() == dwarf::DW_TAG_atomic_type)
ResolvedType = DerivedTy->getBaseType();
}

if (!ResolvedType) {
assert((Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST ||
Kind == BTF::BTF_KIND_VOLATILE) &&
Expand Down Expand Up @@ -800,6 +806,10 @@ void BTFDebug::visitDerivedType(const DIDerivedType *DTy, uint32_t &TypeId,
bool CheckPointer, bool SeenPointer) {
unsigned Tag = DTy->getTag();

if (Tag == dwarf::DW_TAG_atomic_type)
return visitTypeEntry(DTy->getBaseType(), TypeId, CheckPointer,
SeenPointer);

/// Try to avoid chasing pointees, esp. structure pointees which may
/// unnecessary bring in a lot of types.
if (CheckPointer && !SeenPointer) {
Expand Down Expand Up @@ -1444,8 +1454,15 @@ void BTFDebug::processGlobals(bool ProcessingMapDef) {
DIGlobal = GVE->getVariable();
if (SecName.starts_with(".maps"))
visitMapDefType(DIGlobal->getType(), GVTypeId);
else
visitTypeEntry(DIGlobal->getType(), GVTypeId, false, false);
else {
const DIType *Ty = DIGlobal->getType();
if (Ty) {
auto *DTy = dyn_cast<DIDerivedType>(Ty);
if (DTy && DTy->getTag() == dwarf::DW_TAG_atomic_type)
Ty = DTy->getBaseType();
}
visitTypeEntry(Ty, GVTypeId, false, false);
}
break;
}

Expand Down

0 comments on commit 8b82c54

Please sign in to comment.