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