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