1 //===- llvm/BinaryFormat/COFF.cpp - The COFF format -----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/BinaryFormat/COFF.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/ADT/Twine.h"
13 // Maximum offsets for different string table entry encodings.
14 enum : unsigned { Max7DecimalOffset
= 9999999U };
15 enum : uint64_t { MaxBase64Offset
= 0xFFFFFFFFFULL
}; // 64^6, including 0
17 // Encode a string table entry offset in base 64, padded to 6 chars, and
18 // prefixed with a double slash: '//AAAAAA', '//AAAAAB', ...
19 // Buffer must be at least 8 bytes large. No terminating null appended.
20 static void encodeBase64StringEntry(char *Buffer
, uint64_t Value
) {
21 assert(Value
> Max7DecimalOffset
&& Value
<= MaxBase64Offset
&&
22 "Illegal section name encoding for value");
24 static const char Alphabet
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
25 "abcdefghijklmnopqrstuvwxyz"
31 char *Ptr
= Buffer
+ 7;
32 for (unsigned i
= 0; i
< 6; ++i
) {
33 unsigned Rem
= Value
% 64;
35 *(Ptr
--) = Alphabet
[Rem
];
39 bool llvm::COFF::encodeSectionName(char *Out
, uint64_t Offset
) {
40 if (Offset
<= Max7DecimalOffset
) {
41 // Offsets of 7 digits or less are encoded in ASCII.
42 SmallVector
<char, COFF::NameSize
> Buffer
;
43 Twine('/').concat(Twine(Offset
)).toVector(Buffer
);
44 assert(Buffer
.size() <= COFF::NameSize
&& Buffer
.size() >= 2);
45 std::memcpy(Out
, Buffer
.data(), Buffer
.size());
49 if (Offset
<= MaxBase64Offset
) {
50 // Starting with 10,000,000, offsets are encoded as base64.
51 encodeBase64StringEntry(Out
, Offset
);
55 // The offset is too large to be encoded.