diff --git a/llvm/lib/Target/BPF/BTF.h b/llvm/lib/Target/BPF/BTF.h --- a/llvm/lib/Target/BPF/BTF.h +++ b/llvm/lib/Target/BPF/BTF.h @@ -180,8 +180,16 @@ enum : uint8_t { VAR_STATIC = 0, ///< Linkage: InternalLinkage VAR_GLOBAL_ALLOCATED = 1, ///< Linkage: ExternalLinkage - VAR_GLOBAL_TENTATIVE = 2, ///< Linkage: CommonLinkage - VAR_GLOBAL_EXTERNAL = 3, ///< Linkage: ExternalLinkage + VAR_GLOBAL_EXTERNAL = 2, ///< Linkage: ExternalLinkage + VAR_GLOBAL_TENTATIVE = 3, ///< Linkage: CommonLinkage +}; + +/// For external variables, the following additional information +/// for what the external is intended to be used. +enum : uint8_t { + EXT_VAR_CROSS_MODULE = 0, ///< Cross modules + EXT_VAR_LINUX = 1, ///< From linux kernel + EXT_VAR_CURR_MODULE = 2, ///< Current module }; /// BTF_KIND_DATASEC are followed by multiple "struct BTFDataSecVar". diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -1055,67 +1055,82 @@ // Collect all types referenced by globals. const Module *M = MMI->getModule(); for (const GlobalVariable &Global : M->globals()) { - // Ignore external globals for now. - if (!Global.hasInitializer() && Global.hasExternalLinkage()) - continue; + // Support all globals: + // . static: VAR_STATIC, in DataSec. + // . initialized global (0 or non-0): VAR_GLOBAL_ALLOCATED, in DataSec. + // . external global: VAR_GLOBAL_EXTERNAL, not in DataSec. + // . common global: VAR_GLOBAL_TENTATIVE, not in DataSec. + // Whether DataSec is readonly or not can be found from the + // corresponding ELF section flags. // Decide the section name. - StringRef SecName; - if (Global.hasSection()) { - SecName = Global.getSection(); - } else { - // data, bss, or readonly sections - if (Global.isConstant()) - SecName = ".rodata"; + // CommonLinkage variables do not have section names. + StringRef DataSecName; + uint32_t GVarScope, GVarDetails = 0; + auto Linkage = Global.getLinkage(); + if (Global.hasInitializer() && Linkage != GlobalValue::CommonLinkage) { + if (Global.hasSection()) { + DataSecName = Global.getSection(); + } else { + // data, bss, or readonly sections + if (Global.isConstant()) + DataSecName = ".rodata"; + else + DataSecName = Global.getInitializer()->isZeroValue() ? ".bss" : ".data"; + } + if (Linkage == GlobalValue::InternalLinkage) + GVarScope = BTF::VAR_STATIC; else - SecName = Global.getInitializer()->isZeroValue() ? ".bss" : ".data"; + GVarScope = BTF::VAR_GLOBAL_ALLOCATED; + } else if (Linkage == GlobalValue::CommonLinkage) { + GVarScope = BTF::VAR_GLOBAL_TENTATIVE; + } else { + // External variables. + GVarScope = BTF::VAR_GLOBAL_EXTERNAL; + StringRef ExtSecName = Global.getSection(); + if (ExtSecName == "bpf_linux") + GVarDetails = BTF::EXT_VAR_LINUX; + else if (ExtSecName == "bpf_curr_module") + GVarDetails = BTF::EXT_VAR_CURR_MODULE; + else if (ExtSecName == "bpf_cross_module") + GVarDetails = BTF::EXT_VAR_CROSS_MODULE; + else // What is proper action here? + GVarDetails = BTF::EXT_VAR_CROSS_MODULE; } - if (ProcessingMapDef != SecName.startswith(".maps")) + if (ProcessingMapDef != DataSecName.startswith(".maps")) continue; SmallVector GVs; Global.getDebugInfo(GVs); uint32_t GVTypeId = 0; for (auto *GVE : GVs) { - if (SecName.startswith(".maps")) + if (DataSecName.startswith(".maps")) visitMapDefType(GVE->getVariable()->getType(), GVTypeId); else visitTypeEntry(GVE->getVariable()->getType(), GVTypeId, false, false); break; } - // Only support the following globals: - // . static variables - // . non-static global variables with section attributes - // Essentially means: - // . .bcc/.data/.rodata DataSec entities only contain static data - // . Other DataSec entities contain static or initialized global data. - // Initialized global data are mostly used for finding map key/value type - // id's. Whether DataSec is readonly or not can be found from - // corresponding ELF section flags. - auto Linkage = Global.getLinkage(); - if (Linkage != GlobalValue::InternalLinkage && - (Linkage != GlobalValue::ExternalLinkage || !Global.hasSection())) - continue; - - uint32_t GVarInfo = Linkage == GlobalValue::ExternalLinkage - ? BTF::VAR_GLOBAL_ALLOCATED - : BTF::VAR_STATIC; + // Var Scope now takes the lowest 4 bits in the 32bit value. + uint32_t GVarInfo = (GVarDetails << 4) | GVarScope; auto VarEntry = std::make_unique(Global.getName(), GVTypeId, GVarInfo); uint32_t VarId = addType(std::move(VarEntry)); + if (DataSecName.empty()) + continue; + // Find or create a DataSec - if (DataSecEntries.find(SecName) == DataSecEntries.end()) { - DataSecEntries[SecName] = std::make_unique(Asm, SecName); + if (DataSecEntries.find(DataSecName) == DataSecEntries.end()) { + DataSecEntries[DataSecName] = std::make_unique(Asm, DataSecName); } // Calculate symbol size const DataLayout &DL = Global.getParent()->getDataLayout(); uint32_t Size = DL.getTypeAllocSize(Global.getType()->getElementType()); - DataSecEntries[SecName]->addVar(VarId, Asm->getSymbol(&Global), Size); + DataSecEntries[DataSecName]->addVar(VarId, Asm->getSymbol(&Global), Size); } }