LLVM 개조에 대한 이야기

17862 단어 C++LinuxLLVMsparctech

SPARC를 사용한 LLVM 구축


최근에는 더 이상 SPARC 기계를 보지 못했다.
이런 가운데'다음 알파벳 J'의 기기는 SPARC로, LLVM을 구축해 설치하고 싶다(2017년 12월)는 말이 나온다.

LVM은 SPARC를 지원합니까?


다음 2017년에 Oracle Coller팀의 Fedor Sergeev는 메일 리스트에 버전 5 이전에 SPARC에 대응하기를 희망한다고 밝혔다.
https://lists.llvm.org/pipermail/llvm-dev/2017-June/114437.html
LLVM의 버전 3.9.1을 실제로 수정했습니다.
이 버전에서는 SPARC도 지원되지 않습니다.

안 맞으면 코드만 쓸 수 있어요.


그럼 지원을 위해 코드 구축만 할 수 있습니다.
조건은 월면 착륙 임무만큼 어렵다.

조사를 시작하다


우선 부족한 점이 있습니까?
LLVM의 소스를 다운받아 조사한다(소박하니 거기서부터 시작해라, 역시 거기서부터 시작해라).
LLVM의 최신 버전 12.0.1(20221.09.23 기준)
https://github.com/llvm/llvm-project
SPARC 등의 키워드 Grep으로 관계가 있을 만한 곳을 찾아라.
관점을 바꾸어 Intel과 지원되기 때문에 Intel의 처리가 있지만 SPARC가 처리하지 않은 곳을 찾습니다.
여기 SPARC의 정의가 있어요.
※ 버전 3.9.1과 버전 12.0.1의 목록 구성이 변경된 버전 12.01
llvm-project-main/llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def
#ifndef ELF_RELOC
#error "ELF_RELOC must be defined"
#endif

ELF_RELOC(R_SPARC_NONE,         0)
ELF_RELOC(R_SPARC_8,            1)
ELF_RELOC(R_SPARC_16,           2)
ELF_RELOC(R_SPARC_32,           3)
ELF_RELOC(R_SPARC_DISP8,        4)
ELF_RELOC(R_SPARC_DISP16,       5)
ELF_RELOC(R_SPARC_DISP32,       6)
ELF_RELOC(R_SPARC_WDISP30,      7)
ELF_RELOC(R_SPARC_WDISP22,      8)
ELF_RELOC(R_SPARC_HI22,         9)
ELF_RELOC(R_SPARC_22,           10)
ELF_RELOC(R_SPARC_13,           11)
ELF_RELOC(R_SPARC_LO10,         12)
ELF_RELOC(R_SPARC_GOT10,        13)
ELF_RELOC(R_SPARC_GOT13,        14)
ELF_RELOC(R_SPARC_GOT22,        15)
ELF_RELOC(R_SPARC_PC10,         16)
ELF_RELOC(R_SPARC_PC22,         17)
ELF_RELOC(R_SPARC_WPLT30,       18)
ELF_RELOC(R_SPARC_COPY,         19)
ELF_RELOC(R_SPARC_GLOB_DAT,     20)
:(途中省略)
ELF_RELOC(R_SPARC_TLS_DTPOFF32,   76)
ELF_RELOC(R_SPARC_TLS_DTPOFF64,   77)
ELF_RELOC(R_SPARC_TLS_TPOFF32,    78)
ELF_RELOC(R_SPARC_TLS_TPOFF64,    79)
ELF_RELOC(R_SPARC_GOTDATA_HIX22,  80)
ELF_RELOC(R_SPARC_GOTDATA_LOX10,  81)
ELF_RELOC(R_SPARC_GOTDATA_OP_HIX22,  82)
ELF_RELOC(R_SPARC_GOTDATA_OP_LOX10,  83)
ELF_RELOC(R_SPARC_GOTDATA_OP,     84)
Intel(x86 64)이 있지만 SPARC는 없습니다.
llvm-project-main/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
// The target location for the relocation is described by RE.SectionID and
// RE.Offset.  RE.SectionID can be used to find the SectionEntry.  Each
// SectionEntry has three members describing its location.
// SectionEntry::Address is the address at which the section has been loaded
// into memory in the current (host) process.  SectionEntry::LoadAddress is the
// address that the section will have in the target process.
// SectionEntry::ObjAddress is the address of the bits for this section in the
// original emitted object image (also in the current address space).
//
// Relocations will be applied as if the section were loaded at
// SectionEntry::LoadAddress, but they will be applied at an address based
// on SectionEntry::Address.  SectionEntry::ObjAddress will be used to refer to
// Target memory contents if they are required for value calculations.
//
// The Value parameter here is the load address of the symbol for the
// relocation to be applied.  For relocations which refer to symbols in the
// current object Value will be the LoadAddress of the section in which
// the symbol resides (RE.Addend provides additional information about the
// symbol location).  For external symbols, Value will be the address of the
// symbol in the target address space.
void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE,
                                       uint64_t Value) {
  const SectionEntry &Section = Sections[RE.SectionID];
  return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
                           RE.SymOffset, RE.SectionID);
}

void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
                                       uint64_t Offset, uint64_t Value,
                                       uint32_t Type, int64_t Addend,
                                       uint64_t SymOffset, SID SectionID) {
  switch (Arch) {
  case Triple::x86_64:
    resolveX86_64Relocation(Section, Offset, Value, Type, Addend, SymOffset);
    break;
  case Triple::x86:
    resolveX86Relocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type,
                         (uint32_t)(Addend & 0xffffffffL));
    break;
  case Triple::aarch64:
  case Triple::aarch64_be:
    resolveAArch64Relocation(Section, Offset, Value, Type, Addend);
    break;
  case Triple::arm: // Fall through.
  case Triple::armeb:
  case Triple::thumb:
  case Triple::thumbeb:
    resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type,
                         (uint32_t)(Addend & 0xffffffffL));
    break;
  case Triple::ppc: // Fall through.
  case Triple::ppcle:
    resolvePPC32Relocation(Section, Offset, Value, Type, Addend);
    break;
  case Triple::ppc64: // Fall through.
  case Triple::ppc64le:
    resolvePPC64Relocation(Section, Offset, Value, Type, Addend);
    break;
  case Triple::systemz:
    resolveSystemZRelocation(Section, Offset, Value, Type, Addend);
    break;
  case Triple::bpfel:
  case Triple::bpfeb:
    resolveBPFRelocation(Section, Offset, Value, Type, Addend);
    break;
  default:
    llvm_unreachable("Unsupported CPU type!");
  }
}
※ 이렇게 쉽게 찾을 수 있는 것은 아니다.

ELF 소개


Linux와 같은 UNIX 시스템 OS에서는 객체 파일과 실행 형식의 파일 형식이 이 ELF(Executable and Linking Formt)를 사용합니다.
상기 Intel에 있지만 SPARC에 없는 처리는 각 프로세서의 ELF가 재구성한 부분에 SPARC의 재구성 처리가 없는 것이다. 즉, SPARC를 통해 실행 형식 파일을 만들 수 없다는 것이다.

SPARC의 ELF를 재구성하려면 어떻게 해야 합니까?


과연 SPARC는 누구의 것일까요?
처음에는 SUN 마이크로시스템이었습니다.갑골문은 그걸 수령 중입니다.
그래서 자료는 Oracle 웹 사이트에 게재되어야 합니다.
그래서
Oracle sparc elf
이런 키워드를 넣어 곤두박질치다.
다음 사이트는 곧 성공할 것이다.
https://docs.oracle.com/cd/E37932_01/html/E36753/chapter6-43405.html
링컨 같은 거.
일본어로 ELF라고 쓰여 있어요.
사이트 왼쪽의 메뉴에는 64개의 SPARC가 있습니다. 리셋형이 매력적이라고 생각합니다.
여기는 빙고입니다.
표12-17x64: ELF 재배치형의 표 중 임의의 재배치 방식이 이번에 필요한 조건에 대응하는 알파벳 J의 아래.
따라서 표 중 하나를 찾으면 프로그래밍 재설정 처리가 완료됩니다.
송이경(신지현):야!
실제 프로그래밍에서는 비트의 위치 이동과 교체 등 간단한 처리를 설명할 수 있다.
일부분은 올려놓을게요.맛만 보세요.
  • 재구성 유형 이름(값): RSPARC_DISP32(6)
  • case ELF::R_SPARC_DISP32:
    	// S + A を計算
    	Value += Addend;
    	// セクションのアドレスの値をポインタ値に設定
    	TargetPtr32 = reinterpret_cast<uint32_t*>(TargetAddress);
    	// S + A の値に - P を計算
    	*TargetPtr32 = (Value - reinterpret_cast<uintptr_t>(TargetPtr32));
    	break;
    

    달에 오르는 느낌.


    2017년 말∼2018년 초를 돌이켜보면 LLVM 등 컴파일러를 기반으로 공개된 자료도 개조할 수 없는 것은 아니라는 생각에 잠겼다.

    좋은 웹페이지 즐겨찾기