1 /* 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.oracle.ipack.macho; 27 28 import com.oracle.ipack.util.Util; 29 import java.io.DataInput; 30 import java.io.DataOutput; 31 import java.io.IOException; 32 import java.util.ArrayList; 33 34 public final class MachoHeader { 35 private ArrayList<MachoCommand> commands; 36 37 private int magic; 38 private int cpuType; 39 private int cpuSubType; 40 private int fileType; 41 private int flags; 42 43 public MachoHeader() { 44 commands = new ArrayList<MachoCommand>(); 45 } 46 47 public MachoCommand findCommand(final int commandId) { 48 for (final MachoCommand command: commands) { 49 if (command.getId() == commandId) { 50 return command; 51 } 52 } 53 54 return null; 55 } 56 57 public SegmentCommand findSegment(final String segmentName) { 58 for (final MachoCommand command: commands) { 59 if (command.getId() == MachoCommand.LC_SEGMENT) { 60 final SegmentCommand segmentCommand = (SegmentCommand) command; 61 if (segmentName.equals(segmentCommand.getSegmentName())) { 62 return segmentCommand; 63 } 64 } 65 } 66 67 return null; 68 } 69 70 public void addCommand(final MachoCommand command) { 71 commands.add(command); 72 } 73 74 public static MachoHeader read(final DataInput dataInput) 75 throws IOException { 76 final MachoHeader header = new MachoHeader(); 77 header.readImpl(dataInput); 78 return header; 79 } 80 81 public int getSize() { 82 int size = 7 * 4; 83 for (final MachoCommand command: commands) { 84 size += command.getSize(); 85 } 86 87 return size; 88 } 89 90 public int getMagic() { 91 return magic; 92 } 93 94 public void setMagic(final int magic) { 95 this.magic = magic; 96 } 97 98 public int getCpuType() { 99 return cpuType; 100 } 101 102 public void setCpuType(final int cpuType) { 103 this.cpuType = cpuType; 104 } 105 106 public int getCpuSubType() { 107 return cpuSubType; 108 } 109 110 public void setCpuSubType(final int cpuSubType) { 111 this.cpuSubType = cpuSubType; 112 } 113 114 public int getFileType() { 115 return fileType; 116 } 117 118 public void setFileType(final int fileType) { 119 this.fileType = fileType; 120 } 121 122 public int getFlags() { 123 return flags; 124 } 125 126 public void setFlags(final int flags) { 127 this.flags = flags; 128 } 129 130 public void write(final DataOutput dataOutput) throws IOException { 131 dataOutput.writeInt(magic); 132 dataOutput.writeInt(cpuType); 133 dataOutput.writeInt(cpuSubType); 134 dataOutput.writeInt(fileType); 135 dataOutput.writeInt(commands.size()); 136 dataOutput.writeInt(getSizeOfCommands()); 137 dataOutput.writeInt(flags); 138 139 for (final MachoCommand command: commands) { 140 command.write(dataOutput); 141 } 142 } 143 144 private void readImpl(final DataInput dataInput) throws IOException { 145 magic = dataInput.readInt(); 146 cpuType = dataInput.readInt(); 147 cpuSubType = dataInput.readInt(); 148 fileType = dataInput.readInt(); 149 final int numberOfCommands = dataInput.readInt(); 150 final int sizeOfCommands = dataInput.readInt(); 151 flags = dataInput.readInt(); 152 153 int sizeOfReadCommands = 0; 154 commands.clear(); 155 commands.ensureCapacity(numberOfCommands); 156 for (int i = 0; i < numberOfCommands; ++i) { 157 final MachoCommand command = MachoCommand.read(dataInput); 158 commands.add(command); 159 sizeOfReadCommands += command.getSize(); 160 } 161 162 if (sizeOfCommands != sizeOfReadCommands) { 163 throw new IOException("Failed to decode commands"); 164 } 165 } 166 167 private int getSizeOfCommands() { 168 int sizeOfCommands = 0; 169 for (final MachoCommand command: commands) { 170 sizeOfCommands += command.getSize(); 171 } 172 173 return sizeOfCommands; 174 } 175 176 @Override 177 public String toString() { 178 return "Header { magic: 0x" + Util.hex32(magic) 179 + ", cpuType: " + cpuType 180 + ", cpuSubType: " + cpuSubType 181 + ", fileType: " + fileType 182 + ", flags: 0x" + Util.hex32(flags) 183 + ", commands: " + commands + " }"; 184 } 185 }