• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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