1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2020-2021 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
//===- ZEELFObjectBuilder.hpp -----------------------------------*- C++ -*-===//
// ZE Binary Utilities
//
// \file
// This file declares ZEELFObjectBuilder for building an ZE Binary object
//===----------------------------------------------------------------------===//
#ifndef ZE_ELF_OBJECT_BUILDER_HPP
#define ZE_ELF_OBJECT_BUILDER_HPP
#include <ZEELF.h>
#include <ZEInfo.hpp>
#include "inc/common/igfxfmid.h"
#ifndef ZEBinStandAloneBuild
#include "common/LLVMWarningsPush.hpp"
#endif
#include "llvm/BinaryFormat/ELF.h"
#ifndef ZEBinStandAloneBuild
#include "common/LLVMWarningsPop.hpp"
#endif
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace llvm {
class raw_pwrite_stream;
}
namespace zebin {
/// ZEELFObjectBuilder - Build an ELF Object for ZE binary format
class ZEELFObjectBuilder {
friend class ELFWriter;
public:
// The valid SectionID must be 0 or positive value
typedef int32_t SectionID;
public:
ZEELFObjectBuilder(bool is64Bit) : m_is64Bit(is64Bit)
{
m_metadata.packed = 0;
}
~ZEELFObjectBuilder() {}
void setProductFamily(PRODUCT_FAMILY family) { m_productFamily = family; }
PRODUCT_FAMILY getProductFamily() const { return m_productFamily; }
void setGfxCoreFamily(GFXCORE_FAMILY family) { m_gfxCoreFamily = family; }
GFXCORE_FAMILY getGfxCoreFamily() const { return m_gfxCoreFamily; }
void setTargetMetadata(TargetMetadata metadata) { m_metadata = metadata; }
TargetMetadata getTargetMetadata() const { return m_metadata; }
// add a text section contains gen binary
// - name: section name. This is usually the kernel or function name of
// this text section. Do not includes leading .text in given
// name. For example, giving "kernel", the section name will be
// .text.kernel
// - data: memory buffer of the section contents. This buffer must be live
// through this ZEELFObjectBuilder
// - size: input buffer size in byte
// - padding: required padding at the end
// - align: alignment requirement in byte
// - return a unique id for referencing in addSymbol
// Currently we assume there is only one text section that'll be added
SectionID addSectionText(
std::string name, const uint8_t* data, uint64_t size, uint32_t padding, uint32_t align);
// add a data section contains raw data, such as constant or global buffer.
// - name: section name. Do not includes leading .data in given
// name. For example, giving "const", the section name will be
// .data.const
// - data: memory buffer of the section contents. This buffer must be live through
// this ZEELFObjectBuilder
// - size: input buffer size in byte
// - padding: required padding at the end
// - align: alignment requirement in byte
// - return a unique id for referencing in addSymbol
SectionID addSectionData(
std::string name, const uint8_t* data, uint64_t size, uint32_t padding = 0, uint32_t align = 0, bool rodata = false);
// add a bss section which occupies no space in the ELF, but with size and other section information
// The bss sections could be used for zero-initialized variables.
// - name: section name. Do not includes leading .bss in given name.
// For example, giving "const", the section name will be .bss.const
// - size: input buffer size in byte
// - padding: required padding at the end
// - align: alignment requirement in byte
// - return a unique id for referencing in addSymbol
SectionID addSectionBss(
std::string name, uint64_t size, uint32_t padding = 0, uint32_t align = 0);
// add a spv section contains the spv source. This section will be set to SHT_ZEBIN_SPIRV type
// - name: section name. The default name is .spv
// - size in byte
// - Note that the alignment requirement of the section should be satisfied
// by the given data and size
// - Note that the given data buffer have to be alive through
// ZEELFObjectBuilder
void addSectionSpirv(std::string name, const uint8_t* data, uint64_t size);
// add .gtpin_info section
// - name: section name. Do not includes leading .gtpin_info in the given
// name. For example, giving "func", the section name will be
// ".gtpin_info.func". The default name is .gtpin_fino. It'll be apply
// if the given name is empty.
// - size in byte
// - Note that the alignment requirement of the section should be satisfied
// by the given data and size
// - Note that the given data buffer have to be alive through
// ZEELFObjectBuilder
void addSectionGTPinInfo(std::string name, const uint8_t* data, uint64_t size);
// add .visaasm section
// - name: section name. Do not includes leading .visaasm in the given
// name. For example, giving "func", the section name will be
// ".visaasm.func". The default name is .visaasm. It'll be apply
// if the given name is empty.
// - size in byte
// - Note that the alignment requirement of the section should be satisfied
// by the given data and size
// - Note that the given data buffer have to be alive through ZEELFObjectBuilder
void addSectionVISAAsm(std::string name, const uint8_t* data, uint64_t size);
// add .misc section
// - name: section name. Do not includes leading .misc in the given
// name. For example, giving "func", the section name will be
// ".misc.func". The default name is .misc. It'll be apply
// if the given name is empty.
// - size in byte
// - Note that the alignment requirement of the section should be satisfied
// by the given data and size
// - Note that the given data buffer have to be alive through ZEELFObjectBuilder
void addSectionMisc(std::string name, const uint8_t* data, uint64_t size);
// add .note.intelgt.metrics section
// - name: .note.intelgt.metrics. Do not includes leading .note.intelgt.metrics
// in the given name. For example, giving "func", the section name will be
// ".note.intelgt.metrics.func". The default name is .note.intelgt.metrics.
// It'll be applied if the given name is empty.
// - size in byte
// - Note that the alignment requirement of the section should be satisfied
// by the given data and size
// - Note that the given data buffer have to be alive through ZEELFObjectBuilder
void addSectionMetrics(std::string name, const uint8_t* data, uint64_t size);
// .debug_info section in DWARF format
// - name: section name. The default name is .debug_info
// - size in byte
// - Note that the alignment requirement of the section should be satisfied
// by the given data and size
// - Note that the given data buffer have to be alive through
// ZEELFObjectBuilder
// - return a unique id for referencing in addSymbol
SectionID addSectionDebug(std::string name, const uint8_t* data, uint64_t size);
// add ze_info section
void addSectionZEInfo(zeInfoContainer& zeInfo);
// add a symbol
// - name : symbol's name
// - addr : symbol's address. The binary offset of where this symbol is
// defined in the section
// - size : symbol size
// - binding : symbol binding. The value is defined in ELF standard ST_BIND
// - type : symbol type. The value is defined in ELF standard ST_TYPE
// - sectionId : the section id of which this symbol is defined in. Giving
// -1 if this is an UNDEFINED symbol
void addSymbol(std::string name, uint64_t addr, uint64_t size,
uint8_t binding, uint8_t type, SectionID sectionId);
// add a relocation with rel format
// This function will create a corresponding .rel.{targetSectionName} section if
// not exist
// - offset : the binary offset of the section where the relocation
// will apply to. The section is denoted by sectionId
// - symName : the target symbol's name
// - type : the relocation name
// - sectionId : the section id where the relocation is apply to
void addRelRelocation(
uint64_t offset, std::string symName, R_TYPE_ZEBIN type, SectionID sectionId);
// add a relocation with rela format
// This function will create a corresponding .rela.{targetSectionName} section if
// not exist
// - offset : the binary offset of the section where the relocation
// will apply to. The section is denoted by sectionId
// - symName : the target symbol's name
// - type : the relocation name
// - addend : the addend value
// - sectionId : the section id where the relocation is apply to
void addRelaRelocation(
uint64_t offset, std::string symName, R_TYPE_ZEBIN type, uint64_t addend, SectionID sectionId);
// finalize - Finalize the ELF Object, write ELF file into given os
// return number of written bytes
uint64_t finalize(llvm::raw_pwrite_stream& os);
// get an ID of a section
// - name : section name
SectionID getSectionIDBySectionName(const char* name);
private:
class Section {
public:
enum Kind {STANDARD, RELOC, ZEINFO};
virtual Kind getKind() const = 0;
SectionID id() const { return m_id; }
protected:
Section(uint32_t id) : m_id(id) {}
virtual ~Section() {}
Section(const Section&) = default;
Section& operator=(const Section&) = default;
protected:
SectionID m_id;
};
class StandardSection : public Section {
public:
StandardSection(std::string sectName, const uint8_t* data, uint64_t size,
unsigned type, unsigned flags, uint32_t padding, uint32_t id)
: Section(id), m_sectName(sectName), m_data(data), m_size(size), m_type(type),
m_flags(flags), m_padding(padding)
{}
Kind getKind() const { return STANDARD; }
// m_sectName - the final name presented in ELF section header
// This field is required as the place holder for StringTable construction
std::string m_sectName;
const uint8_t* m_data;
uint64_t m_size;
// section type
unsigned m_type;
unsigned m_flags = 0;
uint32_t m_padding;
};
class ZEInfoSection : public Section {
public:
ZEInfoSection(zeInfoContainer& zeinfo, uint32_t id)
: Section(id), m_zeinfo(zeinfo)
{}
Kind getKind() const { return ZEINFO; }
zeInfoContainer& getZeInfo()
{ return m_zeinfo; }
private:
zeInfoContainer& m_zeinfo;
};
class Symbol {
public:
Symbol(std::string name, uint64_t addr, uint64_t size, uint8_t binding,
uint8_t type, SectionID sectionId)
: m_name(name), m_addr(addr), m_size(size), m_binding(binding),
m_type(type), m_sectionId(sectionId)
{}
std::string& name() { return m_name; }
uint64_t addr() const { return m_addr; }
uint64_t size() const { return m_size; }
uint8_t binding() const { return m_binding; }
uint8_t type() const { return m_type; }
SectionID sectionId() const { return m_sectionId; }
private:
std::string m_name;
uint64_t m_addr;
uint64_t m_size;
uint8_t m_binding;
uint8_t m_type;
SectionID m_sectionId;
};
/// Relocation - present the relocation information of each entry.
/// The relocation itself doesn't know if it's in rel or rela format.
/// It's rel or rela depends on it's in RelocSection or RelaRelocSection
class Relocation {
public:
Relocation(uint64_t offset, std::string symName, R_TYPE_ZEBIN type, uint64_t addend = 0)
: m_offset(offset), m_symName(symName), m_type(type), m_addend(addend)
{}
uint64_t offset() const { return m_offset; }
const std::string& symName() const { return m_symName; }
R_TYPE_ZEBIN type() const { return m_type; }
uint64_t addend() const { return m_addend; }
private:
uint64_t m_offset;
std::string m_symName;
R_TYPE_ZEBIN m_type;
uint64_t m_addend;
};
typedef std::vector<StandardSection> StandardSectionListTy;
typedef std::vector<Symbol> SymbolListTy;
typedef std::vector<Relocation> RelocationListTy;
class RelocSection : public Section {
public:
RelocSection(SectionID myID, SectionID targetID, std::string sectName, bool isRelFormat) :
Section(myID), m_TargetID(targetID), m_sectName(sectName), m_isRelFormat (isRelFormat)
{}
Kind getKind() const { return RELOC; }
bool isRelFormat() const { return m_isRelFormat; }
public:
// target section's id that this relocation section apply to
SectionID m_TargetID;
std::string m_sectName;
RelocationListTy m_Relocations;
// This is a rel or rela relocation format
bool m_isRelFormat;
};
typedef std::vector<RelocSection> RelocSectionListTy;
private:
Section& addStandardSection(
std::string sectName, const uint8_t* data, uint64_t size, unsigned type,
unsigned flags, uint32_t padding, uint32_t align, StandardSectionListTy& sections);
// isRelFormat - rel or rela relocation format
RelocSection& getOrCreateRelocSection(SectionID targetSectId, bool isRelFormat);
std::string getSectionNameBySectionID(SectionID id);
private:
// place holder for section default name
const std::string m_TextName = ".text";
const std::string m_DataName = ".data";
const std::string m_BssName = ".bss";
const std::string m_SymTabName = ".symtab";
const std::string m_RelName = ".rel";
const std::string m_RelaName = ".rela";
const std::string m_SpvName = ".spv";
const std::string m_VISAAsmName = ".visaasm";
const std::string m_DebugName = ".debug_info";
const std::string m_ZEInfoName = ".ze_info";
const std::string m_GTPinInfoName = ".gtpin_info";
const std::string m_MiscName = ".misc";
const std::string m_CompatNoteName = ".note.intelgt.compat";
const std::string m_MetricsNoteName = ".note.intelgt.metrics";
const std::string m_StrTabName = ".strtab";
private:
// 32 or 64 bit object
bool m_is64Bit;
// information used to generate .note.intelgt.compat
PRODUCT_FAMILY m_productFamily = IGFX_UNKNOWN;
GFXCORE_FAMILY m_gfxCoreFamily = IGFX_UNKNOWN_CORE;
TargetMetadata m_metadata;
StandardSectionListTy m_textSections;
StandardSectionListTy m_dataAndbssSections; // data and bss sections
StandardSectionListTy m_otherStdSections;
RelocSectionListTy m_relocSections; // rel and rela reloc sections
// current section id
SectionID m_sectionIdCount = 0;
// every ze object contains at most one ze_info section
std::unique_ptr<ZEInfoSection> m_zeInfoSection;
SymbolListTy m_localSymbols;
SymbolListTy m_globalSymbols;
};
/// ZEInfoBuilder - Build a zeInfoContainer for .ze_info section
class ZEInfoBuilder {
public:
ZEInfoBuilder()
{
mContainer.version = PreDefinedAttrGetter::getVersionNumber();
}
zeInfoContainer& getZEInfoContainer() { return mContainer; }
const zeInfoContainer& getZEInfoContainer() const { return mContainer; }
// empty - return true if there is no kernel/function info in it
bool empty() const;
/// --------- Helper functions for setup zeinfo contents -------------- ///
// createKernel - create a zeInfoKernel and add it into zeInfoContainer
zeInfoKernel& createKernel(const std::string& name);
// createFunction - create a zeInfoFunction and add it into zeInfoContainer
zeInfoFunction& createFunction(const std::string& name);
// createKernelMiscInfo - create a zeKernelMiscInfo and add it into zeInfoContainer
zeInfoKernelMiscInfo& createKernelMiscInfo(const std::string& name);
// addGlobalHostAccessSymbol - create a zeInfo global_host_access_table section
// which is used by Runtime to identify a global variable based on host name
void addGlobalHostAccessSymbol(const std::string& device_name, const std::string& host_name);
// addPayloadArgumentByPointer - add explicit kernel argument with pointer
// type into given arg_list
static zeInfoPayloadArgument& addPayloadArgumentByPointer(
PayloadArgumentsTy& arg_list,
int32_t offset,
int32_t size,
int32_t arg_index,
PreDefinedAttrGetter::ArgAddrMode addrmode,
PreDefinedAttrGetter::ArgAddrSpace addrspace,
PreDefinedAttrGetter::ArgAccessType access_type,
int32_t alignment = 0);
// addPayloadArgumentByValue - add explicit kernel argument with pass by
// value type into given arg_list
static zeInfoPayloadArgument& addPayloadArgumentByValue(
PayloadArgumentsTy& arg_list,
int32_t offset,
int32_t size,
int32_t arg_index,
int32_t source_offset);
// addPayloadArgumentImage - add explicit kernel argument for image
// into given arg_list
// The argument type will be set to by_pointer, and addr_space will be set to image
static zeInfoPayloadArgument& addPayloadArgumentImage(
PayloadArgumentsTy& arg_list,
int32_t offset,
int32_t size,
int32_t arg_index,
PreDefinedAttrGetter::ArgAddrMode addrmode,
PreDefinedAttrGetter::ArgAccessType access_type,
PreDefinedAttrGetter::ArgImageType image_type);
// addPayloadArgumentSampler - add explicit kernel argument for sampler
// into given arg_list
// The argument type will be set to by_pointer, and addr_space will be set to sampler
static zeInfoPayloadArgument& addPayloadArgumentSampler(
PayloadArgumentsTy& arg_list,
int32_t offset,
int32_t size,
int32_t arg_index,
int32_t sampler_index,
PreDefinedAttrGetter::ArgAddrMode addrmode,
PreDefinedAttrGetter::ArgAccessType access_type,
PreDefinedAttrGetter::ArgSamplerType sampler_type);
// addInlineSampler - add inline sampler into given inline_sampler_list.
static zeInfoInlineSampler& addInlineSampler(
InlineSamplersTy& inline_sampler_list,
int32_t sampler_index,
PreDefinedAttrGetter::ArgSamplerAddrMode addr_mode,
PreDefinedAttrGetter::ArgSamplerFilterMode filter_mode,
bool normalized);
// addPayloadArgumentImplicit - add non-user argument (implicit argument)
// into given arg_list. The type must be local_size, group_size,
// global_id_offset or private_base_stateless
static zeInfoPayloadArgument& addPayloadArgumentImplicit(
PayloadArgumentsTy& arg_list,
PreDefinedAttrGetter::ArgType type,
int32_t offset,
int32_t size);
// addPerThreadPayloadArgument - add a per-thread payload argument into
// arg_list. Currently we only support local id as per-thread argument.
// The given type must be packed_local_ids or local_id
static zeInfoPerThreadPayloadArgument& addPerThreadPayloadArgument(
PerThreadPayloadArgumentsTy& arg_list,
PreDefinedAttrGetter::ArgType type,
int32_t offset,
int32_t size);
// addBindingTableIndex - add a binding table index into given bti_list, with
// corresponding kernel argument index
static zeInfoBindingTableIndex& addBindingTableIndex(
BindingTableIndicesTy& bti_list,
int32_t bti_value,
int32_t arg_index);
// addPerThreadMemoryBuffer - add a memory buffer info with global or slm type
// If adding buffer with "global" type, this API assume it is allocated per-hardware-thread
// Use below addPerSIMTThreadGlobalMemoryBuffer API if attempting to add per-simt-thread global buffer
static zeInfoPerThreadMemoryBuffer& addPerThreadMemoryBuffer(
PerThreadMemoryBuffersTy& mem_buff_list,
PreDefinedAttrGetter::MemBufferType type,
PreDefinedAttrGetter::MemBufferUsage usage,
int32_t size);
// addScratchPerThreadMemoryBuffer - add a memory buffer info for scratch buffer
// per_thread_memory_buffers::type set to scratch
static zeInfoPerThreadMemoryBuffer& addScratchPerThreadMemoryBuffer(
PerThreadMemoryBuffersTy& mem_buff_list,
PreDefinedAttrGetter::MemBufferUsage usage,
int32_t slot_id,
int32_t size);
// addPerSIMTThreadGlobalMemoryBuffer - add a memory buffer info
// for global memory buffer with
// per_thread_memory_buffers::type set to global
// per_thread_memory_buffers::is_simt_thread set to true
// Use addPerThreadMemoryBuffer if adding per-hardware-thread global memory buffer
static zeInfoPerThreadMemoryBuffer& addPerSIMTThreadGlobalMemoryBuffer(
PerThreadMemoryBuffersTy& mem_buff_list,
PreDefinedAttrGetter::MemBufferUsage usage,
int32_t size);
// addExpPropertiesHasNonKernelArgLdSt - add experimental_properties for has-non-kernel-arg-load-store analysis
// add experimental_properties::has_non_kernel_arg_load, experimental_properties::has_non_kernel_arg_store
// and experimental_properties::has_non_kernel_arg_atomic
// Note that zeInfoExperimentalProperties is made as a vector under kernel in the spec, because we want it only
// present when needed. If it's not a vector, the attribute name will always present in final output even if
// all of its sub-attributes are default and are not shown.
static void addExpPropertiesHasNonKernelArgLdSt(zeInfoKernel& zekernel,
bool hasNonKernelArgLoad, bool hasNonKernelArgStore, bool hasNonKernelArgAtomic);
private:
zeInfoContainer mContainer;
};
} // end namespace zebin
#endif // ZE_ELF_OBJECT_BUILDER_HPP
|