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

Yonghong Song via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 12 10:01:46 PDT 2018


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();
 }




More information about the llvm-commits mailing list