LLVM 개조에 대한 이야기
SPARC를 사용한 LLVM 구축
최근에는 더 이상 SPARC 기계를 보지 못했다.
이런 가운데'다음 알파벳 J'의 기기는 SPARC로, LLVM을 구축해 설치하고 싶다(2017년 12월)는 말이 나온다.
LVM은 SPARC를 지원합니까?
다음 2017년에 Oracle Coller팀의 Fedor Sergeev는 메일 리스트에 버전 5 이전에 SPARC에 대응하기를 희망한다고 밝혔다.
LLVM의 버전 3.9.1을 실제로 수정했습니다.
이 버전에서는 SPARC도 지원되지 않습니다.
안 맞으면 코드만 쓸 수 있어요.
그럼 지원을 위해 코드 구축만 할 수 있습니다.
조건은 월면 착륙 임무만큼 어렵다.
조사를 시작하다
우선 부족한 점이 있습니까?
LLVM의 소스를 다운받아 조사한다(소박하니 거기서부터 시작해라, 역시 거기서부터 시작해라).
LLVM의 최신 버전 12.0.1(20221.09.23 기준)
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
이런 키워드를 넣어 곤두박질치다.
다음 사이트는 곧 성공할 것이다.
링컨 같은 거.
일본어로 ELF라고 쓰여 있어요.
사이트 왼쪽의 메뉴에는 64개의 SPARC가 있습니다. 리셋형이 매력적이라고 생각합니다.
여기는 빙고입니다.
표12-17x64: ELF 재배치형의 표 중 임의의 재배치 방식이 이번에 필요한 조건에 대응하는 알파벳 J의 아래.
따라서 표 중 하나를 찾으면 프로그래밍 재설정 처리가 완료됩니다.
송이경(신지현):야!
실제 프로그래밍에서는 비트의 위치 이동과 교체 등 간단한 처리를 설명할 수 있다.
일부분은 올려놓을게요.맛만 보세요.
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 등 컴파일러를 기반으로 공개된 자료도 개조할 수 없는 것은 아니라는 생각에 잠겼다.
Reference
이 문제에 관하여(LLVM 개조에 대한 이야기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/open_sesame/articles/939c875fa8e378텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)