[llvm] r344366 - [BPF] Add BTF generation for BPF target

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 12 10:57:38 PDT 2018


Hello, please take more care next time in ensuring that the patch will work
on multiple platforms.  For example, #include <linux/types.h> is obviously
going to break on any platform that isn't linux.

The other issue is C99 designated initializers, which are not supported by
all platforms.

In the future please use types like uint32_t instead of __u32 and don't
include platform specific headers.

On Fri, Oct 12, 2018 at 10:04 AM Yonghong Song via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: yhs
> Date: Fri Oct 12 10:01:46 2018
> New Revision: 344366
>
> URL: http://llvm.org/viewvc/llvm-project?rev=344366&view=rev
> Log:
> [BPF] Add BTF generation for BPF target
>
> BTF is the debug format for BPF, a kernel virtual machine
> and widely used for tracing, networking and security, etc ([1]).
>
> Currently only instruction streams are passed to kernel,
> the kernel verifier verifies them before execution. In order to
> provide better visibility of bpf programs to user space
> tools, some debug information, e.g., function names and
> debug line information are desirable for kernel so tools
> can get such information with better annotation
> for jited instructions for performance or other reasons.
>
> The dwarf is too complicated in kernel and for BPF.
> Hence, BTF is designed to be the debug format for BPF ([2]).
> Right now, pahole supports BTF for types, which
> are generated based on dwarf sections in the ELF file.
>
> In order to annotate performance metrics for jited bpf insns,
> it is necessary to pass debug line info to the kernel.
> Furthermore, we want to pass the actual code to the
> kernel because of the following reasons:
>
> . bpf program typically is small so storage overhead
>   should be small.
> . in bpf land, it is totally possible that
>   an application loads the bpf program into the
>   kernel and then that application quits, so
>   holding debug info by the user space application
>   is not practical.
> . having source codes directly kept by kernel
>   would ease deployment since the original source
>   code does not need ship on every hosts and
>   kernel-devel package does not need to be
>   deployed even if kernel headers are used.
>
> The only reliable time to get the source code is
> during compilation time. This will result in both more
> accurate information and easier deployment as
> stated in the above.
>
> Another consideration is for JIT. The project like bcc
> use MCJIT to compile a C program into bpf insns and
> load them to the kernel ([3]). The generated BTF sections
> will be readily available for such cases as well.
>
> This patch implemented generation of BTF info in llvm
> compiler. The BTF related sections will be generated
> when both -target bpf and -g are specified. Two sections
> are generated:
>   .BTF contains all the type and string information, and
>   .BTF.ext contains the func_info and line_info.
>
> The separation is related to how two sections are used
> differently in bpf loader, e.g., linux libbpf ([4]).
> The .BTF section can be loaded into the kernel directly
> while .BTF.ext needs loader manipulation before loading
> to the kernel. The format of the each section is roughly
> defined in llvm:include/llvm/MC/MCBTFContext.h and
> from the implementation in llvm:lib/MC/MCBTFContext.cpp.
> A later example also shows the contents in each section.
>
> The type and func_info are gathered during CodeGen/AsmPrinter
> by traversing dwarf debug_info. The line_info is
> gathered in MCObjectStreamer before writing to
> the object file. After all the information is gathered,
> the two sections are emitted in MCObjectStreamer::finishImpl.
>
> With cmake CMAKE_BUILD_TYPE=Debug, the compiler can
> dump out all the tables except insn offset, which
> will be resolved later as relocation records.
> The debug type "btf" is used for BTFContext dump.
>
> Dwarf tests the debug info generation with
> llvm-dwarfdump to decode the binary sections and
> check whether the result is expected. Currently
> we do not have such a tool yet. We will implement
> btf dump functionality in bpftool ([5]) as the bpftool is
> considered the recommended tool for bpf introspection.
> The implementation for type and func_info is tested
> with linux kernel test cases. The line_info is visually
> checked with dump from linux kernel libbpf ([4]) and
> checked with readelf dumping section raw data.
>
> Note that the .BTF and .BTF.ext information will not
> be emitted to assembly code and there is no assembler
> support for BTF either.
>
> In the below, with a clang/llvm built with CMAKE_BUILD_TYPE=Debug,
> Each table contents are shown for a simple C program.
>
>   -bash-4.2$ cat -n test.c
>      1  struct A {
>      2    int a;
>      3    char b;
>      4  };
>      5
>      6  int test(struct A *t) {
>      7    return t->a;
>      8  }
>   -bash-4.2$ clang -O2 -target bpf -g -mllvm -debug-only=btf -c test.c
>   Type Table:
>   [1] FUNC name_off=1 info=0x0c000001 size/type=2
>         param_type=3
>   [2] INT name_off=12 info=0x01000000 size/type=4
>         desc=0x01000020
>   [3] PTR name_off=0 info=0x02000000 size/type=4
>   [4] STRUCT name_off=16 info=0x04000002 size/type=8
>         name_off=18 type=2 bit_offset=0
>         name_off=20 type=5 bit_offset=32
>   [5] INT name_off=22 info=0x01000000 size/type=1
>         desc=0x02000008
>
>   String Table:
>   0 :
>   1 : test
>   6 : .text
>   12 : int
>   16 : A
>   18 : a
>   20 : b
>   22 : char
>   27 : test.c
>   34 : int test(struct A *t) {
>   58 :   return t->a;
>
>   FuncInfo Table:
>   sec_name_off=6
>         insn_offset=<Omitted> type_id=1
>
>   LineInfo Table:
>   sec_name_off=6
>         insn_offset=<Omitted> file_name_off=27 line_off=34 line_num=6
> column_num=0
>         insn_offset=<Omitted> file_name_off=27 line_off=58 line_num=7
> column_num=3
>   -bash-4.2$ readelf -S test.o
>   ......
>     [12] .BTF              PROGBITS         0000000000000000  0000028d
>        00000000000000c1  0000000000000000           0     0     1
>     [13] .BTF.ext          PROGBITS         0000000000000000  0000034e
>        0000000000000050  0000000000000000           0     0     1
>     [14] .rel.BTF.ext      REL              0000000000000000  00000648
>        0000000000000030  0000000000000010          16    13     8
>   ......
>   -bash-4.2$
>
> The latest linux kernel ([6]) can already support .BTF with type
> information.
> The [7] has the reference implementation in linux kernel side
> to support .BTF.ext func_info. The .BTF.ext line_info support is not
> implemented yet. If you have difficulty accessing [6], you can
> manually do the following to access the code:
>
>   git clone https://github.com/yonghong-song/bpf-next-linux.git
>   cd bpf-next-linux
>   git checkout btf
>
> The change will push to linux kernel soon once this patch is landed.
>
> References:
> [1]. https://www.kernel.org/doc/Documentation/networking/filter.txt
> [2]. https://lwn.net/Articles/750695/
> [3]. https://github.com/iovisor/bcc
> [4]. https://github.com/torvalds/linux/tree/master/tools/lib/bpf
> [5]. https://github.com/torvalds/linux/tree/master/tools/bpf/bpftool
> [6]. https://github.com/torvalds/linux
> [7]. https://github.com/yonghong-song/bpf-next-linux/tree/btf
>
> Signed-off-by: Song Liu <songliubraving at fb.com>
> Signed-off-by: Yonghong Song <yhs at fb.com>
> Acked-by: Alexei Starovoitov <ast at kernel.org>
>
> Differential Revision: https://reviews.llvm.org/D52950
>
> Added:
>     llvm/trunk/include/llvm/MC/MCBTFContext.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/Dwarf2BTF.h
>     llvm/trunk/lib/MC/MCBTFContext.cpp
>     llvm/trunk/lib/MC/MCDwarf2BTF.cpp
>     llvm/trunk/lib/MC/MCDwarf2BTF.h
> Modified:
>     llvm/trunk/include/llvm/MC/MCContext.h
>     llvm/trunk/include/llvm/MC/MCObjectFileInfo.h
>     llvm/trunk/include/llvm/MC/MCObjectStreamer.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h
>     llvm/trunk/lib/MC/CMakeLists.txt
>     llvm/trunk/lib/MC/MCContext.cpp
>     llvm/trunk/lib/MC/MCObjectFileInfo.cpp
>     llvm/trunk/lib/MC/MCObjectStreamer.cpp
>
> Added: llvm/trunk/include/llvm/MC/MCBTFContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCBTFContext.h?rev=344366&view=auto
>
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCBTFContext.h (added)
> +++ llvm/trunk/include/llvm/MC/MCBTFContext.h Fri Oct 12 10:01:46 2018
> @@ -0,0 +1,364 @@
> +//===- MCBTFContext.h ---------------------------------------- *- C++
> --*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +// This header file contains two parts. The first part is the BTF ELF
> +// specification in C format, and the second part is the various
> +// C++ classes to manipulate the data structure in order to generate
> +// the BTF related ELF sections.
>
> +//===----------------------------------------------------------------------===//
> +#ifndef LLVM_MC_MCBTFCONTEXT_H
> +#define LLVM_MC_MCBTFCONTEXT_H
> +
> +#include <linux/types.h>
> +
> +#define BTF_MAGIC      0xeB9F
> +#define BTF_VERSION    1
> +
> +struct btf_header {
> +       __u16   magic;
> +       __u8    version;
> +       __u8    flags;
> +       __u32   hdr_len;
> +
> +       /* All offsets are in bytes relative to the end of this header */
> +       __u32   type_off;       /* offset of type section       */
> +       __u32   type_len;       /* length of type section       */
> +       __u32   str_off;        /* offset of string section     */
> +       __u32   str_len;        /* length of string section     */
> +};
> +
> +/* Max # of type identifier */
> +#define BTF_MAX_TYPE   0x0000ffff
> +/* Max offset into the string section */
> +#define BTF_MAX_NAME_OFFSET    0x0000ffff
> +/* Max # of struct/union/enum members or func args */
> +#define BTF_MAX_VLEN   0xffff
> +
> +struct btf_type {
> +       __u32 name_off;
> +       /* "info" bits arrangement
> +        * bits  0-15: vlen (e.g. # of struct's members)
> +        * bits 16-23: unused
> +        * bits 24-27: kind (e.g. int, ptr, array...etc)
> +        * bits 28-31: unused
> +        */
> +       __u32 info;
> +       /* "size" is used by INT, ENUM, STRUCT and UNION.
> +        * "size" tells the size of the type it is describing.
> +        *
> +        * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
> +        * FUNC and FUNC_PROTO.
> +        * "type" is a type_id referring to another type.
> +        */
> +       union {
> +               __u32 size;
> +               __u32 type;
> +       };
> +};
> +
> +#define BTF_INFO_KIND(info)    (((info) >> 24) & 0x0f)
> +#define BTF_INFO_VLEN(info)    ((info) & 0xffff)
> +
> +#define BTF_KIND_UNKN          0       /* Unknown      */
> +#define BTF_KIND_INT           1       /* Integer      */
> +#define BTF_KIND_PTR           2       /* Pointer      */
> +#define BTF_KIND_ARRAY         3       /* Array        */
> +#define BTF_KIND_STRUCT                4       /* Struct       */
> +#define BTF_KIND_UNION         5       /* Union        */
> +#define BTF_KIND_ENUM          6       /* Enumeration  */
> +#define BTF_KIND_FWD           7       /* Forward      */
> +#define BTF_KIND_TYPEDEF       8       /* Typedef      */
> +#define BTF_KIND_VOLATILE      9       /* Volatile     */
> +#define BTF_KIND_CONST         10      /* Const        */
> +#define BTF_KIND_RESTRICT      11      /* Restrict     */
> +#define BTF_KIND_FUNC          12      /* Function     */
> +#define BTF_KIND_FUNC_PROTO    13      /* Function Prototype   */
> +#define BTF_KIND_MAX           13
> +#define NR_BTF_KINDS           14
> +
> +/* For some specific BTF_KIND, "struct btf_type" is immediately
> + * followed by extra data.
> + */
> +
> +/* BTF_KIND_INT is followed by a u32 and the following
> + * is the 32 bits arrangement:
> + */
> +#define BTF_INT_ENCODING(VAL)  (((VAL) & 0x0f000000) >> 24)
> +#define BTF_INT_OFFSET(VAL)    (((VAL  & 0x00ff0000)) >> 16)
> +#define BTF_INT_BITS(VAL)      ((VAL)  & 0x000000ff)
> +
> +/* Attributes stored in the BTF_INT_ENCODING */
> +#define BTF_INT_SIGNED (1 << 0)
> +#define BTF_INT_CHAR   (1 << 1)
> +#define BTF_INT_BOOL   (1 << 2)
> +
> +/* BTF_KIND_ENUM is followed by multiple "struct btf_enum".
> + * The exact number of btf_enum is stored in the vlen (of the
> + * info in "struct btf_type").
> + */
> +struct btf_enum {
> +       __u32   name_off;
> +       __s32   val;
> +};
> +
> +/* BTF_KIND_ARRAY is followed by one "struct btf_array" */
> +struct btf_array {
> +       __u32   type;
> +       __u32   index_type;
> +       __u32   nelems;
> +};
> +
> +/* BTF_KIND_STRUCT and BTF_KIND_UNION are followed
> + * by multiple "struct btf_member".  The exact number
> + * of btf_member is stored in the vlen (of the info in
> + * "struct btf_type").
> + */
> +struct btf_member {
> +       __u32   name_off;
> +       __u32   type;
> +       __u32   offset; /* offset in bits */
> +};
> +
> +/* .BTF.ext section contains func_info and line_info.
> + */
> +struct btf_ext_header {
> +       __u16   magic;
> +       __u8    version;
> +       __u8    flags;
> +       __u32   hdr_len;
> +
> +       __u32   func_info_off;
> +       __u32   func_info_len;
> +       __u32   line_info_off;
> +       __u32   line_info_len;
> +};
> +
> +struct bpf_func_info {
> +       __u32   insn_offset;
> +       __u32   type_id;
> +};
> +
> +struct btf_sec_func_info {
> +       __u32   sec_name_off;
> +       __u32   num_func_info;
> +};
> +
> +struct bpf_line_info {
> +       __u32   insn_offset;
> +       __u32   file_name_off;
> +       __u32   line_off;
> +       __u32   line_col; /* line num: line_col >> 10, col num: line_col &
> 0x3ff */
> +};
> +
> +struct btf_sec_line_info {
> +       __u32   sec_name_off;
> +       __u32   num_line_info;
> +};
> +
> +namespace llvm {
> +
> +const char *const btf_kind_str[NR_BTF_KINDS] = {
> +       [BTF_KIND_UNKN]         = "UNKNOWN",
> +       [BTF_KIND_INT]          = "INT",
> +       [BTF_KIND_PTR]          = "PTR",
> +       [BTF_KIND_ARRAY]        = "ARRAY",
> +       [BTF_KIND_STRUCT]       = "STRUCT",
> +       [BTF_KIND_UNION]        = "UNION",
> +       [BTF_KIND_ENUM]         = "ENUM",
> +       [BTF_KIND_FWD]          = "FWD",
> +       [BTF_KIND_TYPEDEF]      = "TYPEDEF",
> +       [BTF_KIND_VOLATILE]     = "VOLATILE",
> +       [BTF_KIND_CONST]        = "CONST",
> +       [BTF_KIND_RESTRICT]     = "RESTRICT",
> +       [BTF_KIND_FUNC]         = "FUNC",
> +       [BTF_KIND_FUNC_PROTO]   = "FUNC_PROTO",
> +};
> +
> +#include "llvm/ADT/SmallVector.h"
> +#include <map>
> +
> +class MCBTFContext;
> +class MCObjectStreamer;
> +
> +// This is base class of all BTF KIND. It is also used directly
> +// by the reference kinds:
> +//   BTF_KIND_CONST,  BTF_KIND_PTR,  BTF_KIND_VOLATILE,
> +//   BTF_KIND_TYPEDEF, BTF_KIND_RESTRICT, and BTF_KIND_FWD
> +class BTFTypeEntry {
> +protected:
> +  size_t Id;  /* type index in the BTF list, started from 1 */
> +  struct btf_type BTFType;
> +
> +public:
> +  BTFTypeEntry(size_t id, struct btf_type &type) :
> +    Id(id), BTFType(type) {}
> +  unsigned char getKind() { return BTF_INFO_KIND(BTFType.info); }
> +  void setId(size_t Id) { this->Id = Id; }
> +  size_t getId() { return Id; }
> +  void setNameOff(unsigned NameOff) { BTFType.name_off = NameOff; }
> +
> +  unsigned getTypeIndex() { return BTFType.type; }
> +  unsigned getNameOff() { return BTFType.name_off; }
> +  virtual size_t getSize() { return sizeof(struct btf_type); }
> +  virtual void print(raw_ostream &s, MCBTFContext& BTFContext);
> +  virtual void emitData(MCObjectStreamer *MCOS);
> +};
> +
> +// BTF_KIND_INT
> +class BTFTypeEntryInt : public BTFTypeEntry {
> +  unsigned IntVal;  // encoding, offset, bits
> +
> +public:
> +  BTFTypeEntryInt(size_t id, struct btf_type &type, unsigned intval) :
> +    BTFTypeEntry(id, type), IntVal(intval) {}
> +  size_t getSize() { return BTFTypeEntry::getSize() + sizeof(unsigned); }
> +  void print(raw_ostream &s, MCBTFContext& BTFContext);
> +  void emitData(MCObjectStreamer *MCOS);
> +};
> +
> +// BTF_KIND_ENUM
> +class BTFTypeEntryEnum : public BTFTypeEntry {
> +  std::vector<struct btf_enum> EnumValues;
> +
> +public:
> +  BTFTypeEntryEnum(size_t id, struct btf_type &type,
> +                   std::vector<struct btf_enum> &values) :
> +    BTFTypeEntry(id, type), EnumValues(values) {}
> +  size_t getSize() {
> +    return BTFTypeEntry::getSize() +
> +      BTF_INFO_VLEN(BTFType.info) * sizeof(struct btf_enum);
> +  }
> +  void print(raw_ostream &s, MCBTFContext& BTFContext);
> +  void emitData(MCObjectStreamer *MCOS);
> +};
> +
> +// BTF_KIND_ARRAY
> +class BTFTypeEntryArray : public BTFTypeEntry {
> +  struct btf_array ArrayInfo;
> +
> +public:
> +  BTFTypeEntryArray(size_t id, struct btf_type &type,
> +                    struct btf_array &arrayinfo) :
> +    BTFTypeEntry(id, type), ArrayInfo(arrayinfo) {}
> +  size_t getSize() {
> +    return BTFTypeEntry::getSize() +  sizeof(struct btf_array);
> +  }
> +  void print(raw_ostream &s, MCBTFContext& BTFContext);
> +  void emitData(MCObjectStreamer *MCOS);
> +};
> +
> +// BTF_KIND_STRUCT and BTF_KIND_UNION
> +class BTFTypeEntryStruct : public BTFTypeEntry {
> +  std::vector<struct btf_member> Members;
> +
> +public:
> +  BTFTypeEntryStruct(size_t id, struct btf_type &type,
> +                     std::vector<struct btf_member> &members) :
> +    BTFTypeEntry(id, type), Members(members) {}
> +  size_t getSize() {
> +    return BTFTypeEntry::getSize() +
> +      BTF_INFO_VLEN(BTFType.info) * sizeof(struct btf_member);
> +  }
> +  void print(raw_ostream &s, MCBTFContext& BTFContext);
> +  void emitData(MCObjectStreamer *MCOS);
> +};
> +
> +// BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
> +class BTFTypeEntryFunc : public BTFTypeEntry {
> +  std::vector<unsigned> Parameters;
> +
> +public:
> +  BTFTypeEntryFunc(size_t id, struct btf_type &type,
> +                   std::vector<unsigned> &params) :
> +    BTFTypeEntry(id, type), Parameters(params) {}
> +  size_t getSize() {
> +    return BTFTypeEntry::getSize() +
> +      BTF_INFO_VLEN(BTFType.info) * sizeof(unsigned);
> +  }
> +  void print(raw_ostream &s, MCBTFContext& BTFContext);
> +  void emitData(MCObjectStreamer *MCOS);
> +};
> +
> +class BTFStringTable {
> +  size_t Size;  // total size in bytes
> +  std::map<size_t, unsigned> OffsetToIdMap;
> +  std::vector<std::string> Table;
> +
> + public:
> +  BTFStringTable() : Size(0) {}
> +  size_t getSize() { return Size; }
> +  std::vector<std::string> &getTable() { return Table; }
> +  size_t addString(std::string S) {
> +    // check whether the string already exists
> +    for (auto &OffsetM : OffsetToIdMap) {
> +      if (Table[OffsetM.second] == S)
> +        return OffsetM.first;
> +    }
> +    // not find, add to the string table
> +    size_t Offset = Size;
> +    OffsetToIdMap[Offset] = Table.size();
> +    Table.push_back(S);
> +    Size += S.size() + 1;
> +    return Offset;
> +  }
> +  std::string &getStringAtOffset(size_t Offset) {
> +    return Table[OffsetToIdMap[Offset]];
> +  }
> +  void showTable(raw_ostream &OS) {
> +    for (auto OffsetM : OffsetToIdMap)
> +      OS << OffsetM.first << " : " << Table[OffsetM.second]
> +         << "\n";
> +  }
> +};
> +
> +struct BTFFuncInfo  {
> +    const MCSymbol *Label;
> +    unsigned int TypeId;
> +};
> +
> +struct BTFLineInfo  {
> +    MCSymbol *Label;
> +    unsigned int FileNameOff;
> +    unsigned int LineOff;
> +    unsigned int LineNum;
> +    unsigned int ColumnNum;
> +};
> +
> +class MCBTFContext {
> +  std::vector<std::unique_ptr<BTFTypeEntry>> TypeEntries;
> +  BTFStringTable StringTable;
> +  std::map<unsigned, std::vector<BTFFuncInfo>> FuncInfoTable;
> +  std::map<unsigned, std::vector<BTFLineInfo>> LineInfoTable;
> +
> +  friend class BTFTypeEntry;
> +  friend class BTFTypeEntryInt;
> +  friend class BTFTypeEntryEnum;
> +  friend class BTFTypeEntryArray;
> +  friend class BTFTypeEntryStruct;
> +  friend class BTFTypeEntryFunc;
> +
> +public:
> +  void dump(raw_ostream& OS);
> +  void emitAll(MCObjectStreamer *MCOS);
> +  void emitCommonHeader(MCObjectStreamer *MCOS);
> +  void emitBTFSection(MCObjectStreamer *MCOS);
> +  void emitBTFExtSection(MCObjectStreamer *MCOS);
> +
> +  size_t addString(std::string S) {
> +    return StringTable.addString(S);
> +  }
> +  void addTypeEntry(std::unique_ptr<BTFTypeEntry> Entry);
> +  void addFuncInfo(unsigned SecNameOff, BTFFuncInfo Info) {
> +    FuncInfoTable[SecNameOff].push_back(Info);
> +  }
> +  void addLineInfo(unsigned SecNameOff, BTFLineInfo Info) {
> +    LineInfoTable[SecNameOff].push_back(Info);
> +  }
> +};
> +
> +}
> +#endif
>
> Modified: llvm/trunk/include/llvm/MC/MCContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCContext.h?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCContext.h (original)
> +++ llvm/trunk/include/llvm/MC/MCContext.h Fri Oct 12 10:01:46 2018
> @@ -56,6 +56,7 @@ namespace llvm {
>    class MCSymbolWasm;
>    class SMLoc;
>    class SourceMgr;
> +  class MCBTFContext;
>
>    /// Context object for machine code objects.  This class owns all of the
>    /// sections that it creates.
> @@ -278,6 +279,9 @@ namespace llvm {
>      /// Map of currently defined macros.
>      StringMap<MCAsmMacro> MacroMap;
>
> +    /// for BTF debug information
> +    std::unique_ptr<MCBTFContext> BTFCtx;
> +
>    public:
>      explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI,
>                         const MCObjectFileInfo *MOFI,
> @@ -286,6 +290,9 @@ namespace llvm {
>      MCContext &operator=(const MCContext &) = delete;
>      ~MCContext();
>
> +    void setBTFContext(std::unique_ptr<MCBTFContext> Ctx);
> +    std::unique_ptr<MCBTFContext> &getBTFContext() { return BTFCtx; }
> +
>      const SourceMgr *getSourceManager() const { return SrcMgr; }
>
>      void setInlineSourceManager(SourceMgr *SM) { InlineSrcMgr = SM; }
>
> Modified: llvm/trunk/include/llvm/MC/MCObjectFileInfo.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectFileInfo.h?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCObjectFileInfo.h (original)
> +++ llvm/trunk/include/llvm/MC/MCObjectFileInfo.h Fri Oct 12 10:01:46 2018
> @@ -207,6 +207,10 @@ protected:
>    MCSection *SXDataSection;
>    MCSection *GFIDsSection;
>
> +  // BTF specific sections.
> +  MCSection *BTFSection;
> +  MCSection *BTFExtSection;
> +
>  public:
>    void InitMCObjectFileInfo(const Triple &TT, bool PIC, MCContext &ctx,
>                              bool LargeCodeModel = false);
> @@ -372,6 +376,10 @@ public:
>      return EHFrameSection;
>    }
>
> +  // BTF specific sections.
> +  MCSection *getBTFSection() const { return BTFSection; }
> +  MCSection *getBTFExtSection() const { return BTFExtSection; }
> +
>    enum Environment { IsMachO, IsELF, IsCOFF, IsWasm };
>    Environment getObjectFileType() const { return Env; }
>
>
> Modified: llvm/trunk/include/llvm/MC/MCObjectStreamer.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectStreamer.h?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCObjectStreamer.h (original)
> +++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h Fri Oct 12 10:01:46 2018
> @@ -138,6 +138,7 @@ public:
>                                  unsigned PointerSize);
>    void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
>                                   const MCSymbol *Label);
> +  void EmitBTFAdvanceLineAddr(const MCSymbol *Label, unsigned Size);
>    void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned
> Line,
>                            unsigned Column, bool PrologueEnd, bool IsStmt,
>                            StringRef FileName, SMLoc Loc) override;
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt Fri Oct 12 10:01:46
> 2018
> @@ -17,6 +17,7 @@ add_llvm_library(LLVMAsmPrinter
>    DwarfFile.cpp
>    DwarfStringPool.cpp
>    DwarfUnit.cpp
> +  Dwarf2BTF.cpp
>    EHStreamer.cpp
>    ErlangGCPrinter.cpp
>    OcamlGCPrinter.cpp
>
> Added: llvm/trunk/lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp?rev=344366&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp (added)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp Fri Oct 12 10:01:46
> 2018
> @@ -0,0 +1,501 @@
> +//===- Dwarf2BTF.cpp ------------------------------------------ *- C++
> --*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#include "DwarfUnit.h"
> +#include "Dwarf2BTF.h"
> +#include "llvm/MC/MCBTFContext.h"
> +#include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCSectionELF.h"
> +
> +namespace llvm {
> +
> +unsigned char Die2BTFEntry::getDieKind(const DIE & Die) {
> +  auto Tag = Die.getTag();
> +
> +  switch (Tag) {
> +    case dwarf::DW_TAG_base_type:
> +      if (getBaseTypeEncoding(Die) == BTF_INVALID_ENCODING)
> +        return BTF_KIND_UNKN;
> +      return BTF_KIND_INT;
> +    case dwarf::DW_TAG_const_type:
> +      return BTF_KIND_CONST;
> +    case dwarf::DW_TAG_pointer_type:
> +      return BTF_KIND_PTR;
> +    case dwarf::DW_TAG_restrict_type:
> +      return BTF_KIND_RESTRICT;
> +    case dwarf::DW_TAG_volatile_type:
> +      return BTF_KIND_VOLATILE;
> +    case dwarf::DW_TAG_typedef:
> +      return BTF_KIND_TYPEDEF;
> +    case dwarf::DW_TAG_structure_type:
> +    case dwarf::DW_TAG_class_type:
> +      if (Die.findAttribute(dwarf::DW_AT_declaration).getType()
> +          != DIEValue::isNone)
> +        return BTF_KIND_FWD;
> +      else
> +        return BTF_KIND_STRUCT;
> +    case dwarf::DW_TAG_union_type:
> +      if (Die.findAttribute(dwarf::DW_AT_declaration).getType()
> +          != DIEValue::isNone)
> +        return BTF_KIND_FWD;
> +      else
> +        return BTF_KIND_UNION;
> +    case dwarf::DW_TAG_enumeration_type:
> +      return BTF_KIND_ENUM;
> +    case dwarf::DW_TAG_array_type:
> +      return BTF_KIND_ARRAY;
> +    case dwarf::DW_TAG_subprogram:
> +      return BTF_KIND_FUNC;
> +    case dwarf::DW_TAG_subroutine_type:
> +      return BTF_KIND_FUNC_PROTO;
> +    default:
> +      break;
> +  }
> +
> +  return BTF_KIND_UNKN;
> +}
> +
> +std::unique_ptr<Die2BTFEntry> Die2BTFEntry::dieToBTFTypeEntry(const DIE
> &Die) {
> +  unsigned char Kind = getDieKind(Die);
> +
> +  switch (Kind) {
> +    case BTF_KIND_INT:
> +      return make_unique<Die2BTFEntryInt>(Die);
> +    case BTF_KIND_PTR:
> +    case BTF_KIND_TYPEDEF:
> +    case BTF_KIND_VOLATILE:
> +    case BTF_KIND_CONST:
> +    case BTF_KIND_RESTRICT:
> +    case BTF_KIND_FWD:
> +      return make_unique<Die2BTFEntry>(Die);
> +    case BTF_KIND_ARRAY:
> +      return make_unique<Die2BTFEntryArray>(Die);
> +    case BTF_KIND_STRUCT:
> +    case BTF_KIND_UNION:
> +      return make_unique<Die2BTFEntryStruct>(Die);
> +    case BTF_KIND_ENUM:
> +      return make_unique<Die2BTFEntryEnum>(Die);
> +    case BTF_KIND_FUNC:
> +    case BTF_KIND_FUNC_PROTO:
> +      return make_unique<Die2BTFEntryFunc>(Die);
> +    default:
> +      break;
> +  }
> +  return nullptr;
> +}
> +
> +bool Die2BTFEntry::shouldSkipDie(const DIE &Die) {
> +  auto Tag = Die.getTag();
> +
> +  switch (Tag) {
> +    case dwarf::DW_TAG_const_type:
> +    case dwarf::DW_TAG_pointer_type:
> +    case dwarf::DW_TAG_restrict_type:
> +    case dwarf::DW_TAG_typedef:
> +    case dwarf::DW_TAG_volatile_type:
> +    {
> +      auto TypeV = Die.findAttribute(dwarf::DW_AT_type);
> +      if (TypeV.getType() == DIEValue::isNone)
> +        return false;
> +      auto &TypeDie = TypeV.getDIEEntry().getEntry();
> +      return Die2BTFEntry::shouldSkipDie(TypeDie);
> +    }
> +    default:
> +      return getDieKind(Die) == BTF_KIND_UNKN;
> +  }
> +  return true;
> +}
> +unsigned char Die2BTFEntry::getBaseTypeEncoding(const DIE &Die) {
> +  auto V = Die.findAttribute(dwarf::DW_AT_encoding);
> +
> +  if (V.getType() != DIEValue::isInteger)
> +    return BTF_INVALID_ENCODING;
> +
> +  switch (V.getDIEInteger().getValue()) {
> +    case dwarf::DW_ATE_boolean:
> +      return BTF_INT_BOOL;
> +    case dwarf::DW_ATE_signed:
> +      return BTF_INT_SIGNED;
> +    case dwarf::DW_ATE_signed_char:
> +      return BTF_INT_CHAR;
> +    case dwarf::DW_ATE_unsigned:
> +      return 0;
> +    case dwarf::DW_ATE_unsigned_char:
> +      return BTF_INT_CHAR;
> +    case dwarf::DW_ATE_imaginary_float:
> +    case dwarf::DW_ATE_packed_decimal:
> +    case dwarf::DW_ATE_numeric_string:
> +    case dwarf::DW_ATE_edited:
> +    case dwarf::DW_ATE_signed_fixed:
> +    case dwarf::DW_ATE_address:
> +    case dwarf::DW_ATE_complex_float:
> +    case dwarf::DW_ATE_float:
> +    default:
> +      break;
> +  }
> +  return BTF_INVALID_ENCODING;
> +}
> +
> +Die2BTFEntry::Die2BTFEntry(const DIE &Die) : Die(Die) {
> +  unsigned char Kind = getDieKind(Die);
> +
> +  switch (Kind) {
> +    case BTF_KIND_CONST:
> +    case BTF_KIND_FWD:
> +    case BTF_KIND_PTR:
> +    case BTF_KIND_RESTRICT:
> +    case BTF_KIND_TYPEDEF:
> +    case BTF_KIND_VOLATILE:
> +      break;
> +    default:
> +      assert("Invalid Die passed into BTFTypeEntry()");
> +      break;
> +  }
> +
> +  BTFType.info = (Kind & 0xf) << 24;
> +}
> +
> +void Die2BTFEntry::completeData(class Dwarf2BTF &Dwarf2BTF) {
> +    auto TypeV = Die.findAttribute(dwarf::DW_AT_type);
> +    if (TypeV.getType() == DIEValue::isNone) {
> +      BTFType.type = 0;
> +    } else {
> +      auto &TypeDie = TypeV.getDIEEntry().getEntry();
> +      auto Type = Dwarf2BTF.getTypeIndex(TypeDie);
> +      BTFType.type = Type;
> +    }
> +
> +    unsigned char Kind = getDieKind(Die);
> +    if (Kind != BTF_KIND_FWD) {
> +      BTFType.name_off = 0;
> +    } else {
> +      auto NameV = Die.findAttribute(dwarf::DW_AT_name);
> +      auto Str = NameV.getDIEString().getString();
> +      BTFType.name_off = Dwarf2BTF.addBTFString(Str);
> +    }
> +
> +    auto typeEntry = make_unique<BTFTypeEntry>(Id, BTFType);
> +    Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry));
> +}
> +
> +Die2BTFEntryInt::Die2BTFEntryInt(const DIE &Die) : Die2BTFEntry(Die) {
> +  unsigned char Kind = getDieKind(Die);
> +
> +  switch (Kind) {
> +    case BTF_KIND_INT:
> +      break;
> +    default:
> +      assert("Invalid Die passed into BTFTypeEntryInt()");
> +      break;
> +  }
> +
> +  // handle BTF_INT_ENCODING in IntVal
> +  auto Encoding = Die2BTFEntry::getBaseTypeEncoding(Die);
> +  assert((Encoding != BTF_INVALID_ENCODING) &&
> +         "Invalid Die passed to BTFTypeEntryInt()");
> +  __u32 IntVal = (Encoding & 0xf) << 24;
> +
> +  // handle BTF_INT_OFFSET in IntVal
> +  auto V = Die.findAttribute(dwarf::DW_AT_bit_offset);
> +  if (V.getType() == DIEValue::isInteger)
> +    IntVal |= (V.getDIEInteger().getValue() & 0xff) << 16;
> +
> +  // get btf_type.size
> +  V = Die.findAttribute(dwarf::DW_AT_byte_size);
> +  __u32 Size = V.getDIEInteger().getValue() & 0xffffffff;
> +
> +// handle BTF_INT_BITS in IntVal
> +  V = Die.findAttribute(dwarf::DW_AT_bit_size);
> +  if (V.getType() == DIEValue::isInteger)
> +    IntVal |= V.getDIEInteger().getValue() & 0xff;
> +  else
> +    IntVal |= (Size << 3) & 0xff;
> +
> +  BTFType.info = BTF_KIND_INT << 24;
> +  BTFType.size = Size;
> +  this->IntVal = IntVal;
> +}
> +
> +void Die2BTFEntryInt::completeData(class Dwarf2BTF &Dwarf2BTF) {
> +    auto NameV = Die.findAttribute(dwarf::DW_AT_name);
> +    auto TypeV = Die.findAttribute(dwarf::DW_AT_type);
> +    auto Str = NameV.getDIEString().getString();
> +
> +    BTFType.name_off = Dwarf2BTF.addBTFString(Str);
> +
> +    auto typeEntry = make_unique<BTFTypeEntryInt>(Id, BTFType, IntVal);
> +    Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry));
> +}
> +
> +Die2BTFEntryEnum::Die2BTFEntryEnum(const DIE &Die) : Die2BTFEntry(Die) {
> +  // get btf_type.size
> +  auto V = Die.findAttribute(dwarf::DW_AT_byte_size);
> +  __u32 Size = V.getDIEInteger().getValue() & 0xffffffff;
> +
> +  int Vlen = 0;
> +  for (auto &ChildDie : Die.children())
> +    if (ChildDie.getTag() == dwarf::DW_TAG_enumerator)
> +      Vlen++;
> +
> +  BTFType.info = (BTF_KIND_ENUM << 24) | (Vlen & BTF_MAX_VLEN);
> +  BTFType.type = Size;
> +}
> +
> +void Die2BTFEntryEnum::completeData(class Dwarf2BTF &Dwarf2BTF) {
> +  auto TypeV = Die.findAttribute(dwarf::DW_AT_type);
> +  auto NameV = Die.findAttribute(dwarf::DW_AT_name);
> +
> +  if (NameV.getType() != DIEValue::isNone) {
> +    auto Str = NameV.getDIEString().getString();
> +    BTFType.name_off = Dwarf2BTF.addBTFString(Str);
> +  } else
> +    BTFType.name_off = 0;
> +
> +  for (auto &ChildDie : Die.children()) {
> +    struct btf_enum BTFEnum;
> +    auto ChildNameV = ChildDie.findAttribute(dwarf::DW_AT_name);
> +    auto Str = ChildNameV.getDIEString().getString();
> +
> +    BTFEnum.name_off = Dwarf2BTF.addBTFString(Str);
> +    auto ChildValueV = ChildDie.findAttribute(dwarf::DW_AT_const_value);
> +    BTFEnum.val = (__s32)(ChildValueV.getDIEInteger().getValue());
> +
> +    EnumValues.push_back(BTFEnum);
> +  }
> +
> +  auto typeEntry = make_unique<BTFTypeEntryEnum>(Id, BTFType, EnumValues);
> +  Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry));
> +}
> +
> +Die2BTFEntryArray::Die2BTFEntryArray(const DIE &Die) :
> +    Die2BTFEntry(Die) {
> +  BTFType.info = (BTF_KIND_ARRAY << 24);
> +  BTFType.size = 0;
> +}
> +
> +void Die2BTFEntryArray::completeData(class Dwarf2BTF &Dwarf2BTF) {
> +  auto NameV = Die.findAttribute(dwarf::DW_AT_name);
> +
> +  std::string Str;
> +  if (NameV.getType() != DIEValue::isNone)
> +    Str = NameV.getDIEString().getString();
> +  BTFType.name_off = Dwarf2BTF.addBTFString(Str);
> +
> +  auto &ArrayTypeDie =
> Die.findAttribute(dwarf::DW_AT_type).getDIEEntry().getEntry();
> +  ArrayInfo.type = Dwarf2BTF.getTypeIndex(ArrayTypeDie);
> +
> +  // The number of elements should count all subranges
> +  unsigned Nelems = 1;
> +  bool IsFirstSubrange = true;
> +  for (auto &ChildDie : Die.children()) {
> +    if (ChildDie.getTag() == dwarf::DW_TAG_subrange_type) {
> +      if (IsFirstSubrange) {
> +        auto TypeV = ChildDie.findAttribute(dwarf::DW_AT_type);
> +        auto &TypeDie = TypeV.getDIEEntry().getEntry();
> +        ArrayInfo.index_type = Dwarf2BTF.getTypeIndex(TypeDie);
> +        IsFirstSubrange = false;
> +      }
> +      auto CountV = ChildDie.findAttribute(dwarf::DW_AT_count);
> +      if (CountV.getType() == DIEValue::isNone) {
> +        // array like a[] which essentially a pointer
> +        Nelems = 0;
> +        break;
> +      }
> +      Nelems *= (__u32)(CountV.getDIEInteger().getValue());
> +    }
> +  }
> +  ArrayInfo.nelems = Nelems;
> +
> +  auto TypeEntry = make_unique<BTFTypeEntryArray>(Id, BTFType, ArrayInfo);
> +  Dwarf2BTF.addBTFTypeEntry(std::move(TypeEntry));
> +}
> +
> +Die2BTFEntryStruct::Die2BTFEntryStruct(const DIE &Die) :
> Die2BTFEntry(Die) {
> +  // get btf_type.size
> +  auto V = Die.findAttribute(dwarf::DW_AT_byte_size);
> +  __u32 Size = V.getDIEInteger().getValue() & 0xffffffff;
> +  auto Kind = Die2BTFEntry::getDieKind(Die);
> +
> +  int Vlen = 0;
> +  for (auto &ChildDie : Die.children())
> +    if (ChildDie.getTag() == dwarf::DW_TAG_member)
> +      Vlen++;
> +
> +  BTFType.size = Size;
> +  BTFType.info = (Kind << 24) | (Vlen & BTF_MAX_VLEN);
> +}
> +
> +void Die2BTFEntryStruct::completeData(class Dwarf2BTF &Dwarf2BTF) {
> +  auto NameV = Die.findAttribute(dwarf::DW_AT_name);
> +
> +  if (NameV.getType() != DIEValue::isNone) {
> +    auto Str = NameV.getDIEString().getString();
> +    BTFType.name_off = Dwarf2BTF.addBTFString(Str);
> +  } else
> +    BTFType.name_off = 0;
> +
> +
> +  for (auto &ChildDie : Die.children()) {
> +    if (ChildDie.getTag() != dwarf::DW_TAG_member)
> +      continue;
> +
> +    struct btf_member BTFMember;
> +    auto ChildNameV = ChildDie.findAttribute(dwarf::DW_AT_name);
> +
> +    if (ChildNameV.getType() != DIEValue::isNone) {
> +      auto Str = ChildNameV.getDIEString().getString();
> +      BTFMember.name_off = Dwarf2BTF.addBTFString(Str);
> +    } else
> +      BTFMember.name_off = 0;
> +
> +    auto TypeV = ChildDie.findAttribute(dwarf::DW_AT_type);
> +    auto &TypeDie = TypeV.getDIEEntry().getEntry();
> +    BTFMember.type = Dwarf2BTF.getTypeIndex(TypeDie);
> +
> +    auto MemLocV =
> ChildDie.findAttribute(dwarf::DW_AT_data_member_location);
> +    unsigned MemLoc = MemLocV.getDIEInteger().getValue() * 8;
> +
> +    auto ByteSizeV = ChildDie.findAttribute(dwarf::DW_AT_byte_size);
> +    if (ByteSizeV.getType() != DIEValue::isNone) {
> +      unsigned ByteSize = ByteSizeV.getDIEInteger().getValue();
> +      auto BitOffsetV = ChildDie.findAttribute(dwarf::DW_AT_bit_offset);
> +      unsigned BitOffset = BitOffsetV.getDIEInteger().getValue();
> +      auto BitSizeV = ChildDie.findAttribute(dwarf::DW_AT_bit_size);
> +      unsigned BitSize = BitSizeV.getDIEInteger().getValue();
> +      if (Dwarf2BTF.isLittleEndian())
> +        MemLoc += ByteSize * 8 - BitSize - BitOffset;
> +      else
> +        MemLoc += BitOffset;
> +    }
> +    BTFMember.offset = MemLoc;
> +
> +    Members.push_back(BTFMember);
> +  }
> +
> +  auto typeEntry = make_unique<BTFTypeEntryStruct>(Id, BTFType, Members);
> +  Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry));
> +}
> +
> +Die2BTFEntryFunc::Die2BTFEntryFunc(const DIE &Die) : Die2BTFEntry(Die) {
> +  auto Kind = Die2BTFEntry::getDieKind(Die);
> +
> +  int Vlen = 0;
> +  for (auto &ChildDie : Die.children())
> +    if (ChildDie.getTag() == dwarf::DW_TAG_formal_parameter)
> +      Vlen++;
> +
> +  BTFType.size = 0;
> +  BTFType.info = (Kind << 24) | (Vlen & BTF_MAX_VLEN);
> +}
> +
> +void Die2BTFEntryFunc::completeData(class Dwarf2BTF &Dwarf2BTF) {
> +  auto NameV = Die.findAttribute(dwarf::DW_AT_name);
> +  if (NameV.getType() == DIEValue::isNone) {
> +    BTFType.name_off = 0;
> +  } else {
> +    auto Str = NameV.getDIEString().getString();
> +    BTFType.name_off = Dwarf2BTF.addBTFString(Str);
> +  }
> +
> +  auto RetTypeV = Die.findAttribute(dwarf::DW_AT_type);
> +  if (RetTypeV.getType() != DIEValue::isNone) {
> +    auto &TypeDie = RetTypeV.getDIEEntry().getEntry();
> +    BTFType.type = Dwarf2BTF.getTypeIndex(TypeDie);
> +  } else {
> +    BTFType.type = 0;
> +  }
> +
> +  for (auto &ChildDie : Die.children()) {
> +    if (ChildDie.getTag() == dwarf::DW_TAG_formal_parameter) {
> +      auto TypeV = ChildDie.findAttribute(dwarf::DW_AT_abstract_origin);
> +      if (TypeV.getType() != DIEValue::isNone) {
> +        auto &AbsOriginDie = TypeV.getDIEEntry().getEntry();
> +        assert(AbsOriginDie.getTag() == dwarf::DW_TAG_formal_parameter);
> +        TypeV = AbsOriginDie.findAttribute(dwarf::DW_AT_type);
> +      } else {
> +        TypeV = ChildDie.findAttribute(dwarf::DW_AT_type);
> +      }
> +      auto &TypeDie = TypeV.getDIEEntry().getEntry();
> +      Parameters.push_back(Dwarf2BTF.getTypeIndex(TypeDie));
> +    } else if (ChildDie.getTag() == dwarf::DW_TAG_unspecified_parameters)
> {
> +      Parameters.push_back(0);
> +    }
> +  }
> +
> +  auto typeEntry = make_unique<BTFTypeEntryFunc>(Id, BTFType, Parameters);
> +  Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry));
> +
> +  if (BTF_INFO_KIND(BTFType.info) == BTF_KIND_FUNC) {
> +    auto LowPCV = Die.findAttribute(dwarf::DW_AT_low_pc);
> +    if (LowPCV.getType() != DIEValue::isNone) {
> +      const MCSymbol *Label = LowPCV.getDIELabel().getValue();
> +      BTFFuncInfo FuncInfo;
> +      unsigned SecNameOff;
> +
> +      FuncInfo.Label = Label;
> +      FuncInfo.TypeId = Id;
> +      if (Label->isInSection()) {
> +        MCSection &Section = Label->getSection();
> +        MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section);
> +        assert(SectionELF);
> +        SecNameOff =
> Dwarf2BTF.addBTFString(SectionELF->getSectionName().str());
> +      } else {
> +        SecNameOff = Dwarf2BTF.addBTFString(".text");
> +      }
> +      Dwarf2BTF.addBTFFuncInfo(SecNameOff, FuncInfo);
> +    }
> +  }
> +}
> +
> +Dwarf2BTF::Dwarf2BTF(MCContext &Context, bool IsLittleEndian)
> +  : OuterCtx(Context), IsLE(IsLittleEndian) {
> +  BTFContext = make_unique<MCBTFContext>();
> +}
> +
> +void Dwarf2BTF::addTypeEntry(const DIE &Die) {
> +  for (auto &ChildDie : Die.children())
> +    addTypeEntry(ChildDie);
> +  if (Die2BTFEntry::shouldSkipDie(Die))
> +    return;
> +  auto Kind = Die2BTFEntry::getDieKind(Die);
> +  if (Kind != BTF_KIND_UNKN) {
> +    auto TypeEntry = Die2BTFEntry::dieToBTFTypeEntry(Die);
> +    if (TypeEntry != nullptr) {
> +      TypeEntry->setId(TypeEntries.size() + 1);
> +      DieToIdMap[const_cast<DIE*>(&Die)] = TypeEntry->getId();
> +      TypeEntries.push_back(std::move(TypeEntry));
> +    }
> +  }
> +}
> +
> +void Dwarf2BTF::addBTFTypeEntry(std::unique_ptr<BTFTypeEntry> Entry) {
> +  BTFContext->addTypeEntry(std::move(Entry));
> +}
> +
> +void Dwarf2BTF::completeData() {
> +  BTFContext->addString("\0");
> +
> +  for (auto &TypeEntry : TypeEntries)
> +    TypeEntry->completeData(*this);
> +}
> +
> +void Dwarf2BTF::addDwarfCU(DwarfUnit *TheU) {
> +  DIE &CuDie = TheU->getUnitDie();
> +
> +  assert((CuDie.getTag() == dwarf::DW_TAG_compile_unit) &&
> +         "Not a compile unit");
> +  addTypeEntry(CuDie);
> +}
> +
> +void Dwarf2BTF::finish() {
> +  completeData();
> +  OuterCtx.setBTFContext(std::move(BTFContext));
> +}
> +
> +}
>
> Added: llvm/trunk/lib/CodeGen/AsmPrinter/Dwarf2BTF.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/Dwarf2BTF.h?rev=344366&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/Dwarf2BTF.h (added)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/Dwarf2BTF.h Fri Oct 12 10:01:46 2018
> @@ -0,0 +1,134 @@
> +//===- Dwarf2BTF.h -------------------------------------------- *- C++
> --*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARF2BTF_H
> +#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARF2BTF_H
> +
> +#include "DwarfUnit.h"
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/CodeGen/AsmPrinter.h"
> +#include "llvm/CodeGen/DIE.h"
> +#include "llvm/MC/MCBTFContext.h"
> +#include <map>
> +
> +namespace llvm {
> +
> +class Dwarf2BTF;
> +class MCBTFContext;
> +
> +#define BTF_INVALID_ENCODING 0xff
> +
> +class Die2BTFEntry {
> +protected:
> +  const DIE &Die;
> +  size_t Id;  /* type index in the BTF list, started from 1 */
> +  struct btf_type BTFType;
> +
> +public:
> +  // Return desired BTF_KIND for the Die, return BTF_KIND_UNKN for
> +  // invalid/unsupported Die
> +  static unsigned char getDieKind(const DIE &Die);
> +
> +  // Return proper BTF_INT_ENCODING of a basetype.
> +  // Return BTF_INVALID_ENCODING for unsupported (float, etc.)
> +  static unsigned char getBaseTypeEncoding(const DIE &Die);
> +
> +  // Return whether this Die should be skipped.
> +  // We currently skip unsupported data type (e.g. float)
> +  // and references to unsupported types
> +  static bool shouldSkipDie(const DIE &Die);
> +
> +  static std::unique_ptr<Die2BTFEntry> dieToBTFTypeEntry(const DIE &Die);
> +
> +  Die2BTFEntry(const DIE &Die);
> +  void setId(size_t Id) { this->Id = Id; }
> +  size_t getId() { return Id; }
> +  virtual void completeData(class Dwarf2BTF &Dwarf2BTF);
> +};
> +
> +// BTF_KIND_INT
> +class Die2BTFEntryInt : public Die2BTFEntry {
> +  __u32 IntVal;  // encoding, offset, bits
> +
> +public:
> +  Die2BTFEntryInt(const DIE &Die);
> +  void completeData(class Dwarf2BTF &Dwarf2BTF);
> +};
> +
> +// BTF_KIND_ENUM
> +class Die2BTFEntryEnum : public Die2BTFEntry {
> +  std::vector<struct btf_enum> EnumValues;
> +
> +public:
> +  Die2BTFEntryEnum(const DIE &Die);
> +  void completeData(class Dwarf2BTF &Dwarf2BTF);
> +};
> +
> +// BTF_KIND_ARRAY
> +class Die2BTFEntryArray : public Die2BTFEntry {
> +  struct btf_array ArrayInfo;
> +
> +public:
> +  Die2BTFEntryArray(const DIE &Die);
> +  void completeData(class Dwarf2BTF &Dwarf2BTF);
> +};
> +
> +// BTF_KIND_STRUCT and BTF_KIND_UNION
> +class Die2BTFEntryStruct : public Die2BTFEntry {
> +  std::vector<struct btf_member> Members;
> +
> +public:
> +  Die2BTFEntryStruct(const DIE &Die);
> +  void completeData(class Dwarf2BTF &Dwarf2BTF);
> +};
> +
> +// BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
> +class Die2BTFEntryFunc : public Die2BTFEntry {
> +  std::vector<__u32> Parameters;
> +
> +public:
> +  Die2BTFEntryFunc(const DIE &Die);
> +  void completeData(class Dwarf2BTF &Dwarf2BTF);
> +};
> +
> +class Dwarf2BTF {
> +  std::vector<std::unique_ptr<Die2BTFEntry>> TypeEntries;
> +  std::map<DIE*, size_t> DieToIdMap;
> +  std::unique_ptr<MCBTFContext> BTFContext;
> +  MCContext &OuterCtx;
> +  bool IsLE;
> +
> +public:
> +  Dwarf2BTF(MCContext &Context, bool IsLittleEndian);
> +  bool isLittleEndian() { return IsLE; }
> +  void addDwarfCU(DwarfUnit *TheU);
> +  void finish();
> +  __u32 getTypeIndex(DIE &Die) {
> +    DIE *DiePtr = const_cast<DIE*>(&Die);
> +    assert((DieToIdMap.find(DiePtr) != DieToIdMap.end()) &&
> +           "Die not added to in the BTFContext");
> +    return DieToIdMap[DiePtr];
> +  }
> +  size_t addBTFString(std::string S) {
> +    return BTFContext->addString(S);
> +  }
> +  void addBTFTypeEntry(std::unique_ptr<BTFTypeEntry> Entry);
> +  void addBTFFuncInfo(unsigned SecNameOff, BTFFuncInfo FuncInfo) {
> +    BTFContext->addFuncInfo(SecNameOff, FuncInfo);
> +  }
> +
> +private:
> +  void addTypeEntry(const DIE &Die);
> +  bool alreadyAdded(DIE &Die) {
> +    return DieToIdMap.find(const_cast<DIE*>(&Die)) != DieToIdMap.end();
> +  }
> +  void completeData();
> +};
> +
> +}
> +#endif
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Fri Oct 12 10:01:46
> 2018
> @@ -971,6 +971,10 @@ void DwarfDebug::endModule() {
>    // Emit the pubnames and pubtypes sections if requested.
>    emitDebugPubSections();
>
> +  const Triple &TT = Asm->TM.getTargetTriple();
> +  if (TT.getArch() == Triple::bpfel || TT.getArch() == Triple::bpfeb)
> +    emitBTFSection(TT.getArch() == Triple::bpfel);
> +
>    // clean up.
>    // FIXME: AbstractVariables.clear();
>  }
> @@ -2455,6 +2459,12 @@ MCDwarfDwoLineTable *DwarfDebug::getDwoL
>    return &SplitTypeUnitFileTable;
>  }
>
> +void DwarfDebug::emitBTFSection(bool IsLittleEndian) {
> +  DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
> +
> +  Holder.emitBTFSection(IsLittleEndian);
> +}
> +
>  uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) {
>    MD5 Hash;
>    Hash.update(Identifier);
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Fri Oct 12 10:01:46 2018
> @@ -567,6 +567,9 @@ class DwarfDebug : public DebugHandlerBa
>    /// Emit the reference to the section.
>    void emitSectionReference(const DwarfCompileUnit &CU);
>
> +  // Emit the BTF sections
> +  void emitBTFSection(bool IsLittleEndian);
> +
>  protected:
>    /// Gather pre-function debug information.
>    void beginFunctionImpl(const MachineFunction *MF) override;
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp Fri Oct 12 10:01:46
> 2018
> @@ -7,6 +7,7 @@
>  //
>
>  //===----------------------------------------------------------------------===//
>
> +#include "Dwarf2BTF.h"
>  #include "DwarfFile.h"
>  #include "DwarfCompileUnit.h"
>  #include "DwarfDebug.h"
> @@ -15,6 +16,8 @@
>  #include "llvm/CodeGen/AsmPrinter.h"
>  #include "llvm/CodeGen/DIE.h"
>  #include "llvm/IR/DebugInfoMetadata.h"
> +#include "llvm/MC/MCBTFContext.h"
> +#include "llvm/MC/MCContext.h"
>  #include "llvm/MC/MCStreamer.h"
>  #include <algorithm>
>  #include <cstdint>
> @@ -88,6 +91,13 @@ void DwarfFile::emitStrings(MCSection *S
>    StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
>  }
>
> +void DwarfFile::emitBTFSection(bool IsLittleEndian) {
> +  Dwarf2BTF Dwarf2BTF(Asm->OutContext, IsLittleEndian);
> +  for (auto &TheU : CUs)
> +    Dwarf2BTF.addDwarfCU(TheU.get());
> +  Dwarf2BTF.finish();
> +}
> +
>  bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
>    auto &ScopeVars = ScopeVariables[LS];
>    const DILocalVariable *DV = Var->getVariable();
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h Fri Oct 12 10:01:46 2018
> @@ -114,6 +114,9 @@ public:
>    void emitStrings(MCSection *StrSection, MCSection *OffsetSection =
> nullptr,
>                     bool UseRelativeOffsets = false);
>
> +  // Emit all data for the BTF section
> +  void emitBTFSection(bool IsLittleEndian);
> +
>    /// Returns the string pool.
>    DwarfStringPool &getStringPool() { return StrPool; }
>
>
> Modified: llvm/trunk/lib/MC/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/CMakeLists.txt?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/CMakeLists.txt (original)
> +++ llvm/trunk/lib/MC/CMakeLists.txt Fri Oct 12 10:01:46 2018
> @@ -10,11 +10,13 @@ add_llvm_library(LLVMMC
>    MCAsmMacro.cpp
>    MCAsmStreamer.cpp
>    MCAssembler.cpp
> +  MCBTFContext.cpp
>    MCCodeEmitter.cpp
>    MCCodePadder.cpp
>    MCCodeView.cpp
>    MCContext.cpp
>    MCDwarf.cpp
> +  MCDwarf2BTF.cpp
>    MCELFObjectTargetWriter.cpp
>    MCELFStreamer.cpp
>    MCExpr.cpp
>
> Added: llvm/trunk/lib/MC/MCBTFContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCBTFContext.cpp?rev=344366&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCBTFContext.cpp (added)
> +++ llvm/trunk/lib/MC/MCBTFContext.cpp Fri Oct 12 10:01:46 2018
> @@ -0,0 +1,235 @@
> +//===- lib/MC/MCBTFContext.cpp - Machine Code BTF Context
> -----------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCBTFContext.h"
> +#include "llvm/MC/MCObjectFileInfo.h"
> +#include "llvm/MC/MCObjectStreamer.h"
> +#include "llvm/MC/MCSymbol.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include <cstdlib>
> +#include <tuple>
> +#include <utility>
> +
> +using namespace llvm;
> +
> +#define DEBUG_TYPE "btf"
> +
> +void MCBTFContext::addTypeEntry(std::unique_ptr<BTFTypeEntry> Entry) {
> +   TypeEntries.push_back(std::move(Entry));
> +}
> +
> +void MCBTFContext::dump(raw_ostream &OS) {
> +  OS << "Type Table:\n";
> +  for (size_t i = 0; i < TypeEntries.size(); i++) {
> +    auto TypeEntry = TypeEntries[i].get();
> +    TypeEntry->print(OS, *this);
> +  }
> +
> +  OS << "\nString Table:\n";
> +  StringTable.showTable(OS);
> +
> +  OS << "\nFuncInfo Table:\n";
> +  for (auto &FuncSec : FuncInfoTable) {
> +    OS << "sec_name_off=" << FuncSec.first << "\n";
> +    for (auto &FuncInfo : FuncSec.second) {
> +      OS << "\tinsn_offset=<Omitted> type_id="
> +         << FuncInfo.TypeId << "\n";
> +    }
> +  }
> +
> +  OS << "\nLineInfo Table:\n";
> +  for (auto &LineSec : LineInfoTable) {
> +    OS << "sec_name_off=" << LineSec.first << "\n";
> +    for (auto &LineInfo : LineSec.second) {
> +      OS << "\tinsn_offset=<Omitted> file_name_off="
> +         << LineInfo.FileNameOff
> +         << " line_off=" << LineInfo.LineOff
> +         << " line_num=" << LineInfo.LineNum
> +         << " column_num=" << LineInfo.ColumnNum
> +         << "\n";
> +    }
> +  }
> +}
> +
> +void MCBTFContext::emitCommonHeader(MCObjectStreamer *MCOS) {
> +  MCOS->EmitIntValue(BTF_MAGIC, 2);
> +  MCOS->EmitIntValue(BTF_VERSION, 1);
> +  MCOS->EmitIntValue(0, 1);
> +}
> +
> +void MCBTFContext::emitBTFSection(MCObjectStreamer *MCOS) {
> +  MCContext &context = MCOS->getContext();
> +  MCOS->SwitchSection(context.getObjectFileInfo()->getBTFSection());
> +
> +  // emit header
> +  emitCommonHeader(MCOS);
> +  MCOS->EmitIntValue(sizeof(struct btf_header), 4);
> +
> +  uint32_t type_len = 0, str_len;
> +  for (auto &TypeEntry : TypeEntries)
> +    type_len += TypeEntry->getSize();
> +  str_len = StringTable.getSize();
> +
> +  MCOS->EmitIntValue(0, 4);
> +  MCOS->EmitIntValue(type_len, 4);
> +  MCOS->EmitIntValue(type_len, 4);
> +  MCOS->EmitIntValue(str_len, 4);
> +
> +  // emit type table
> +  for (auto &TypeEntry: TypeEntries)
> +    TypeEntry->emitData(MCOS);
> +
> +  // emit string table
> +  for (auto &S : StringTable.getTable()) {
> +    for (auto C : S)
> +      MCOS->EmitIntValue(C, 1);
> +    MCOS->EmitIntValue('\0', 1);
> +  }
> +}
> +
> +void MCBTFContext::emitBTFExtSection(MCObjectStreamer *MCOS) {
> +  MCContext &context = MCOS->getContext();
> +  MCOS->SwitchSection(context.getObjectFileInfo()->getBTFExtSection());
> +
> +  // emit header
> +  emitCommonHeader(MCOS);
> +  MCOS->EmitIntValue(sizeof(struct btf_ext_header), 4);
> +
> +  uint32_t func_len = 0, line_len = 0;
> +  for (auto &FuncSec : FuncInfoTable) {
> +    func_len += sizeof(struct btf_sec_func_info);
> +    func_len += FuncSec.second.size() * sizeof(struct bpf_func_info);
> +  }
> +  for (auto &LineSec : LineInfoTable) {
> +    line_len += sizeof(struct btf_sec_line_info);
> +    line_len += LineSec.second.size() * sizeof(struct bpf_line_info);
> +  }
> +
> +  MCOS->EmitIntValue(0, 4);
> +  MCOS->EmitIntValue(func_len, 4);
> +  MCOS->EmitIntValue(func_len, 4);
> +  MCOS->EmitIntValue(line_len, 4);
> +
> +  // emit func_info table
> +  for (const auto &FuncSec : FuncInfoTable) {
> +    MCOS->EmitIntValue(FuncSec.first, 4);
> +    MCOS->EmitIntValue(FuncSec.second.size(), 4);
> +    for (const auto &FuncInfo : FuncSec.second) {
> +      MCOS->EmitBTFAdvanceLineAddr(FuncInfo.Label, 4);
> +      MCOS->EmitIntValue(FuncInfo.TypeId, 4);
> +    }
> +  }
> +
> +  // emit line_info table
> +  for (const auto &LineSec : LineInfoTable) {
> +    MCOS->EmitIntValue(LineSec.first, 4);
> +    MCOS->EmitIntValue(LineSec.second.size(), 4);
> +    for (const auto &LineInfo : LineSec.second) {
> +      MCOS->EmitBTFAdvanceLineAddr(LineInfo.Label, 4);
> +      MCOS->EmitIntValue(LineInfo.FileNameOff, 4);
> +      MCOS->EmitIntValue(LineInfo.LineOff, 4);
> +      MCOS->EmitIntValue(LineInfo.LineNum << 10 | LineInfo.ColumnNum, 4);
> +    }
> +  }
> +}
> +
> +void MCBTFContext::emitAll(MCObjectStreamer *MCOS) {
> +  LLVM_DEBUG(dump(dbgs()));
> +  emitBTFSection(MCOS);
> +  emitBTFExtSection(MCOS);
> +}
> +
> +void BTFTypeEntry::print(raw_ostream &OS, MCBTFContext& MCBTFContext) {
> +  OS << "[" << Id << "] "
> +     << btf_kind_str[BTF_INFO_KIND(BTFType.info)]
> +     << " name_off=" << BTFType.name_off
> +     << " info=" << format("0x%08lx", BTFType.info)
> +     << " size/type=" << BTFType.size << "\n";
> +}
> +
> +void BTFTypeEntry::emitData(MCObjectStreamer *MCOS) {
> +  MCOS->EmitIntValue(BTFType.name_off, 4);
> +  MCOS->EmitIntValue(BTFType.info, 4);
> +  MCOS->EmitIntValue(BTFType.size, 4);
> +}
> +
> +void BTFTypeEntryInt::print(raw_ostream &OS, MCBTFContext& MCBTFContext) {
> +  BTFTypeEntry::print(OS, MCBTFContext);
> +  OS << "\tdesc=" << format("0x%08lx", IntVal) << "\n";
> +}
> +
> +void BTFTypeEntryInt::emitData(MCObjectStreamer *MCOS) {
> +  BTFTypeEntry::emitData(MCOS);
> +  MCOS->EmitIntValue(IntVal, 4);
> +}
> +
> +void BTFTypeEntryEnum::print(raw_ostream &OS, MCBTFContext& MCBTFContext)
> {
> + BTFTypeEntry::print(OS, MCBTFContext);
> +  for (size_t i = 0; i < BTF_INFO_VLEN(BTFType.info); i++) {
> +    auto &EnumValue = EnumValues[i];
> +    OS << "\tname_off=" << EnumValue.name_off
> +       << " value=" << EnumValue.val << "\n";
> +  }
> +}
> +
> +void BTFTypeEntryEnum::emitData(MCObjectStreamer *MCOS) {
> +  BTFTypeEntry::emitData(MCOS);
> +  for (auto &EnumValue : EnumValues) {
> +    MCOS->EmitIntValue(EnumValue.name_off, 4);
> +    MCOS->EmitIntValue(EnumValue.val, 4);
> +  }
> +}
> +
> +void BTFTypeEntryArray::print(raw_ostream &OS, MCBTFContext&
> MCBTFContext) {
> +  BTFTypeEntry::print(OS, MCBTFContext);
> +  OS << "\telem_type=" << format("0x%08lx", ArrayInfo.type)
> +     << " index_type=" << format("0x%08lx", ArrayInfo.index_type)
> +     << " num_element=" << ArrayInfo.nelems << "\n";
> +}
> +
> +void BTFTypeEntryArray::emitData(MCObjectStreamer *MCOS) {
> +  BTFTypeEntry::emitData(MCOS);
> +  MCOS->EmitIntValue(ArrayInfo.type, 4);
> +  MCOS->EmitIntValue(ArrayInfo.index_type, 4);
> +  MCOS->EmitIntValue(ArrayInfo.nelems, 4);
> +}
> +
> +void BTFTypeEntryStruct::print(raw_ostream &OS, MCBTFContext&
> MCBTFContext) {
> +  BTFTypeEntry::print(OS, MCBTFContext);
> +   for (size_t i = 0; i < BTF_INFO_VLEN(BTFType.info); i++) {
> +    auto &Member = Members[i];
> +    OS << "\tname_off=" << Member.name_off
> +       << " type=" << Member.type
> +       << " bit_offset=" << Member.offset << "\n";
> +  }
> +}
> +
> +void BTFTypeEntryStruct::emitData(MCObjectStreamer *MCOS) {
> +  BTFTypeEntry::emitData(MCOS);
> +  for (auto &Member : Members) {
> +    MCOS->EmitIntValue(Member.name_off, 4);
> +    MCOS->EmitIntValue(Member.type, 4);
> +    MCOS->EmitIntValue(Member.offset, 4);
> +  }
> +}
> +
> +void BTFTypeEntryFunc::print(raw_ostream &OS, MCBTFContext& MCBTFContext)
> {
> +  BTFTypeEntry::print(OS, MCBTFContext);
> +   for (size_t i = 0; i < BTF_INFO_VLEN(BTFType.info); i++) {
> +    auto Parameter = Parameters[i];
> +    OS << "\tparam_type=" << Parameter << "\n";
> +  }
> +}
> +
> +void BTFTypeEntryFunc::emitData(MCObjectStreamer *MCOS) {
> +  BTFTypeEntry::emitData(MCOS);
> +  for (auto &Parameter: Parameters)
> +    MCOS->EmitIntValue(Parameter, 4);
> +}
>
> Modified: llvm/trunk/lib/MC/MCContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCContext.cpp?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCContext.cpp (original)
> +++ llvm/trunk/lib/MC/MCContext.cpp Fri Oct 12 10:01:46 2018
> @@ -17,6 +17,7 @@
>  #include "llvm/BinaryFormat/COFF.h"
>  #include "llvm/BinaryFormat/ELF.h"
>  #include "llvm/MC/MCAsmInfo.h"
> +#include "llvm/MC/MCBTFContext.h"
>  #include "llvm/MC/MCCodeView.h"
>  #include "llvm/MC/MCDwarf.h"
>  #include "llvm/MC/MCExpr.h"
> @@ -60,7 +61,7 @@ MCContext::MCContext(const MCAsmInfo *ma
>      : SrcMgr(mgr), InlineSrcMgr(nullptr), MAI(mai), MRI(mri), MOFI(mofi),
>        Symbols(Allocator), UsedNames(Allocator),
>        CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0),
> -      AutoReset(DoAutoReset) {
> +      AutoReset(DoAutoReset), BTFCtx(nullptr) {
>    SecureLogFile = AsSecureLogFileName;
>
>    if (SrcMgr && SrcMgr->getNumBuffers())
> @@ -114,6 +115,14 @@ void MCContext::reset() {
>    GenDwarfFileNumber = 0;
>
>    HadError = false;
> +  BTFCtx.reset();
> +}
> +
>
> +//===----------------------------------------------------------------------===//
> +// BTFCtx Manipulation
>
> +//===----------------------------------------------------------------------===//
> +void MCContext::setBTFContext(std::unique_ptr<MCBTFContext> Ctx) {
> +  BTFCtx = std::move(Ctx);
>  }
>
>
>  //===----------------------------------------------------------------------===//
>
> Added: llvm/trunk/lib/MC/MCDwarf2BTF.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDwarf2BTF.cpp?rev=344366&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCDwarf2BTF.cpp (added)
> +++ llvm/trunk/lib/MC/MCDwarf2BTF.cpp Fri Oct 12 10:01:46 2018
> @@ -0,0 +1,99 @@
> +//===- MCDwarf2BTF.cpp ---------------------------------------- *- C++
> --*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#include "MCDwarf2BTF.h"
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/MC/MCAsmInfo.h"
> +#include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCObjectStreamer.h"
> +#include "llvm/MC/MCSection.h"
> +#include "llvm/MC/MCSectionELF.h"
> +#include "llvm/MC/MCBTFContext.h"
> +#include "llvm/Support/Endian.h"
> +#include "llvm/Support/EndianStream.h"
> +#include <fstream>
> +
> +using namespace llvm;
> +
> +void MCDwarf2BTF::addFiles(MCObjectStreamer *MCOS, std::string &FileName,
> +  std::vector<FileContent> &Files) {
> +  std::vector<std::string> Content;
> +
> +  std::ifstream Inputfile(FileName);
> +  std::string Line;
> +  Content.push_back(Line); // line 0 for empty string
> +  while (std::getline(Inputfile, Line))
> +    Content.push_back(Line);
> +
> +  Files.push_back(FileContent(FileName, Content));
> +}
> +
> +void MCDwarf2BTF::addLines(MCObjectStreamer *MCOS, StringRef &SectionName,
> +  std::vector<FileContent> &Files,
> +  const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
> +  MCContext &Context = MCOS->getContext();
> +  auto &BTFCxt = Context.getBTFContext();
> +
> +  unsigned SecNameOff = BTFCxt->addString(SectionName.str());
> +  for (const MCDwarfLineEntry &LineEntry : LineEntries) {
> +    BTFLineInfo LineInfo;
> +    unsigned FileNum = LineEntry.getFileNum();
> +    unsigned Line = LineEntry.getLine();
> +
> +    LineInfo.Label = LineEntry.getLabel();
> +    if (FileNum < Files.size()) {
> +      LineInfo.FileNameOff = BTFCxt->addString(Files[FileNum].first);
> +      if (Line < Files[FileNum].second.size())
> +        LineInfo.LineOff = BTFCxt->addString(Files[FileNum].second[Line]);
> +      else
> +        LineInfo.LineOff = 0;
> +    } else {
> +      LineInfo.FileNameOff = 0;
> +      LineInfo.LineOff = 0;
> +    }
> +    LineInfo.LineNum = Line;
> +    LineInfo.ColumnNum = LineEntry.getColumn();
> +    BTFCxt->addLineInfo(SecNameOff, LineInfo);
> +  }
> +}
> +
> +void MCDwarf2BTF::addDwarfLineInfo(MCObjectStreamer *MCOS) {
> +  MCContext &Context = MCOS->getContext();
> +
> +  auto &LineTables = Context.getMCDwarfLineTables();
> +  if (LineTables.empty())
> +    return;
> +
> +  for (const auto &CUIDTablePair : LineTables) {
> +    std::vector<std::string> Dirs;
> +    std::vector<FileContent> Files;
> +
> +    for (auto &Dir : CUIDTablePair.second.getMCDwarfDirs())
> +      Dirs.push_back(Dir);
> +    for (auto &File : CUIDTablePair.second.getMCDwarfFiles()) {
> +      std::string FileName;
> +      if (File.DirIndex == 0)
> +        FileName = File.Name;
> +      else
> +        FileName = Dirs[File.DirIndex - 1] + "/" + File.Name;
> +      MCDwarf2BTF::addFiles(MCOS, FileName, Files);
> +    }
> +    for (const auto &LineSec:
> CUIDTablePair.second.getMCLineSections().getMCLineEntries()) {
> +      MCSection *Section = LineSec.first;
> +      const MCLineSection::MCDwarfLineEntryCollection &LineEntries =
> LineSec.second;
> +
> +      StringRef SectionName;
> +      if (MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(Section))
> +        SectionName = SectionELF->getSectionName();
> +      else
> +        return;
> +      MCDwarf2BTF::addLines(MCOS, SectionName, Files, LineEntries);
> +    }
> +  }
> +}
>
> Added: llvm/trunk/lib/MC/MCDwarf2BTF.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDwarf2BTF.h?rev=344366&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCDwarf2BTF.h (added)
> +++ llvm/trunk/lib/MC/MCDwarf2BTF.h Fri Oct 12 10:01:46 2018
> @@ -0,0 +1,29 @@
> +//===- MCDwarf2BTF.h ------------------------------------------ *- C++
> --*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +#ifndef LLVM_LIB_MC_MCDWARF2BTF_H
> +#define LLVM_LIB_MC_MCDWARF2BTF_H
> +
> +#include "llvm/MC/MCDwarf.h"
> +
> +namespace llvm {
> +
> +using FileContent = std::pair<std::string, std::vector<std::string>>;
> +
> +class MCDwarf2BTF {
> +public:
> +  static void addFiles(MCObjectStreamer *MCOS, std::string &FileName,
> +    std::vector<FileContent> &Files);
> +  static void addLines(MCObjectStreamer *MCOS, StringRef &SectionName,
> +    std::vector<FileContent> &Files,
> +    const MCLineSection::MCDwarfLineEntryCollection &LineEntries);
> +  static void addDwarfLineInfo(MCObjectStreamer *MCOS);
> +};
> +
> +}
> +#endif
>
> Modified: llvm/trunk/lib/MC/MCObjectFileInfo.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectFileInfo.cpp?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCObjectFileInfo.cpp (original)
> +++ llvm/trunk/lib/MC/MCObjectFileInfo.cpp Fri Oct 12 10:01:46 2018
> @@ -468,6 +468,9 @@ void MCObjectFileInfo::initELFMCObjectFi
>        Ctx->getELFSection(".eh_frame", EHSectionType, EHSectionFlags);
>
>    StackSizesSection = Ctx->getELFSection(".stack_sizes",
> ELF::SHT_PROGBITS, 0);
> +
> +  BTFSection = Ctx->getELFSection(".BTF", ELF::SHT_PROGBITS, 0);
> +  BTFExtSection = Ctx->getELFSection(".BTF.ext", ELF::SHT_PROGBITS, 0);
>  }
>
>  void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
>
> Modified: llvm/trunk/lib/MC/MCObjectStreamer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectStreamer.cpp?rev=344366&r1=344365&r2=344366&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCObjectStreamer.cpp (original)
> +++ llvm/trunk/lib/MC/MCObjectStreamer.cpp Fri Oct 12 10:01:46 2018
> @@ -14,6 +14,7 @@
>  #include "llvm/MC/MCCodeEmitter.h"
>  #include "llvm/MC/MCCodeView.h"
>  #include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCBTFContext.h"
>  #include "llvm/MC/MCDwarf.h"
>  #include "llvm/MC/MCExpr.h"
>  #include "llvm/MC/MCObjectWriter.h"
> @@ -21,6 +22,7 @@
>  #include "llvm/MC/MCSymbol.h"
>  #include "llvm/Support/ErrorHandling.h"
>  #include "llvm/Support/SourceMgr.h"
> +#include "MCDwarf2BTF.h"
>  using namespace llvm;
>
>  MCObjectStreamer::MCObjectStreamer(MCContext &Context,
> @@ -439,6 +441,31 @@ void MCObjectStreamer::EmitDwarfAdvanceF
>    insert(new MCDwarfCallFrameFragment(*AddrDelta));
>  }
>
> +void MCObjectStreamer::EmitBTFAdvanceLineAddr(const MCSymbol *Label,
> +                                              unsigned Size) {
> +  const MCExpr *Value = MCSymbolRefExpr::create(Label, getContext());
> +  MCDataFragment *DF = getOrCreateDataFragment();
> +
> +  // Avoid fixups when possible.
> +  int64_t AbsValue;
> +  SMLoc Loc;
> +
> +  if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {
> +    if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {
> +      getContext().reportError(
> +          Loc, "value evaluated as " + Twine(AbsValue) + " is out of
> range.");
> +      return;
> +    }
> +    EmitIntValue(AbsValue, Size);
> +    return;
> +  }
> +
> +  DF->getFixups().push_back(
> +      MCFixup::create(DF->getContents().size(), Value,
> +                      MCFixup::getKindForSize(Size, false), Loc));
> +  DF->getContents().resize(DF->getContents().size() + Size, 0);
> +}
> +
>  void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned
> FileNo,
>                                            unsigned Line, unsigned Column,
>                                            bool PrologueEnd, bool IsStmt,
> @@ -688,6 +715,13 @@ void MCObjectStreamer::FinishImpl() {
>    // Dump out the dwarf file & directory tables and line tables.
>    MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams());
>
> +  auto &BTFCtx = getContext().getBTFContext();
> +  if (BTFCtx) {
> +    MCDwarf2BTF::addDwarfLineInfo(this);
> +    BTFCtx->emitAll(this);
> +    BTFCtx.reset();
> +  }
> +
>    flushPendingLabels();
>    getAssembler().Finish();
>  }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20181012/11836865/attachment.html>


More information about the llvm-commits mailing list