1 /* 2 * Copyright (c) 2024-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package com.ohos.hapsigntool.codesigning.elf; 17 18 import com.ohos.hapsigntool.codesigning.exception.CodeSignErrMsg; 19 import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; 20 import com.ohos.hapsigntool.zip.UnsignedDecimalUtil; 21 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.nio.ByteBuffer; 25 import java.nio.ByteOrder; 26 27 /** 28 * ELF header info 29 * 30 * @since 2024/07/01 31 */ 32 public class ElfHeader { 33 /** 34 * Magic number and other info 35 */ 36 private byte[] ident = new byte[ElfDefine.EI_NIDENT_LEN]; 37 38 private boolean isElfFile; 39 40 /** 41 * 32-bit or 64-bit file 42 */ 43 private byte eiClass; 44 45 /** 46 * LITTLE_ENDIAN or BIG_ENDIAN 47 */ 48 private byte eiData; 49 50 /** 51 * elf version 52 */ 53 private byte eiVersion; 54 55 /** 56 * Object file type 57 */ 58 private short eType; 59 60 /** 61 * Architecture 62 */ 63 private int eMachine; 64 65 /** 66 * Object file version 67 */ 68 private int eVersion; 69 70 /** 71 * Entry point virtual address 72 */ 73 private long eEntry; 74 75 /** 76 * Program header table file offset 77 */ 78 private long ePhOff; 79 80 /** 81 * Section header table file offset 82 */ 83 private long eShOff; 84 85 /** 86 * Processor-specific flags 87 */ 88 private int eFlags; 89 90 /** 91 * ELF header size in bytes 92 */ 93 private short eEhSize; 94 95 /** 96 * Program header table entry size 97 */ 98 private short ePhEntSize; 99 100 /** 101 * Program header table entry count 102 */ 103 private int ePhNum; 104 105 /** 106 * Section header table entry size 107 */ 108 private short eShEntSize; 109 110 /** 111 * Section header table entry count 112 */ 113 private short eShNum; 114 115 /** 116 * Section header string table index 117 */ 118 private short eShStrndx; 119 120 /** 121 * Constructor for ElfHeader 122 * 123 * @param is InputStream 124 * @throws IOException io error 125 * @throws ElfFormatException elf file format error 126 */ ElfHeader(InputStream is)127 public ElfHeader(InputStream is) throws IOException, ElfFormatException { 128 int read = is.read(ident); 129 isElfFile = isElfFile(ident); 130 if (read != ident.length || !isElfFile) { 131 return; 132 } 133 eiClass = ident[4]; 134 eiData = ident[5]; 135 eiVersion = ident[6]; 136 int len; 137 if (eiClass == ElfDefine.ELF_32_CLASS) { 138 len = ElfDefine.ELF_HEADER_32_LEN - ElfDefine.EI_NIDENT_LEN; 139 } else if (eiClass == ElfDefine.ELF_64_CLASS) { 140 len = ElfDefine.ELF_HEADER_64_LEN - ElfDefine.EI_NIDENT_LEN; 141 } else { 142 throw new ElfFormatException(CodeSignErrMsg.ELF_FILE_HEADER_ERROR.toString("ei_class")); 143 } 144 ByteOrder bo; 145 if (eiData == ElfDefine.ELF_DATA_2_LSB) { 146 bo = ByteOrder.LITTLE_ENDIAN; 147 } else if (eiData == ElfDefine.ELF_DATA_2_MSB) { 148 bo = ByteOrder.BIG_ENDIAN; 149 } else { 150 throw new ElfFormatException(CodeSignErrMsg.ELF_FILE_HEADER_ERROR.toString("ei_data")); 151 } 152 byte[] bytes = new byte[len]; 153 read = is.read(bytes); 154 if (read != len) { 155 throw new ElfFormatException(CodeSignErrMsg.ELF_FILE_HEADER_ERROR.toString("header")); 156 } 157 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); 158 byteBuffer.order(bo); 159 initHeader(byteBuffer); 160 } 161 initHeader(ByteBuffer byteBuffer)162 private void initHeader(ByteBuffer byteBuffer) { 163 eType = byteBuffer.getShort(); 164 eMachine = byteBuffer.getShort(); 165 eVersion = byteBuffer.getInt(); 166 167 if (eiClass == ElfDefine.ELF_32_CLASS) { 168 eEntry = UnsignedDecimalUtil.getUnsignedInt(byteBuffer); 169 ePhOff = UnsignedDecimalUtil.getUnsignedInt(byteBuffer); 170 eShOff = UnsignedDecimalUtil.getUnsignedInt(byteBuffer); 171 } else { 172 eEntry = byteBuffer.getLong(); 173 ePhOff = byteBuffer.getLong(); 174 eShOff = byteBuffer.getLong(); 175 } 176 eFlags = byteBuffer.getInt(); 177 eEhSize = byteBuffer.getShort(); 178 ePhEntSize = byteBuffer.getShort(); 179 ePhNum = UnsignedDecimalUtil.getUnsignedShort(byteBuffer); 180 eShEntSize = byteBuffer.getShort(); 181 eShNum = byteBuffer.getShort(); 182 eShStrndx = byteBuffer.getShort(); 183 } 184 getEiClass()185 public byte getEiClass() { 186 return eiClass; 187 } 188 getEiData()189 public byte getEiData() { 190 return eiData; 191 } 192 getEPhOff()193 public long getEPhOff() { 194 return ePhOff; 195 } 196 getEPhnum()197 public int getEPhnum() { 198 return ePhNum; 199 } 200 201 /** 202 * elf file start with [0x7F 0x45 0x4C 0x46] 203 * 204 * @param bytes byte array 205 * @return true if start with [0x7F 0x45 0x4C 0x46] 206 */ isElfFile(byte[] bytes)207 public static boolean isElfFile(byte[] bytes) { 208 if (bytes == null || bytes.length < 4) { 209 return false; 210 } 211 return bytes[0] == 0x7F && bytes[1] == 0x45 && bytes[2] == 0x4C && bytes[3] == 0x46; 212 } 213 214 /** 215 * return true if magic number is correct 216 * 217 * @return true if magic number is correct 218 */ isElfFile()219 public boolean isElfFile() { 220 return isElfFile; 221 } 222 } 223