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 SegmentCommand extends MachoCommand {
  35     private final ArrayList<Section> sections;
  36 
  37     private String segmentName;
  38     private int vmAddress;
  39     private int vmSize;
  40     private int fileOffset;
  41     private int fileSize;
  42     private int maxVmProtection;
  43     private int initVmProtection;
  44     private int flags;
  45 
  46     public SegmentCommand() {
  47         sections = new ArrayList<Section>();
  48     }
  49 
  50     @Override
  51     public int getId() {
  52         return LC_SEGMENT;
  53     }
  54 
  55     public Section findSection(final String sectionName) {
  56         for (final Section section: sections) {
  57             if (sectionName.equals(section.getSectionName())) {
  58                 return section;
  59             }
  60         }
  61 
  62         return null;
  63     }
  64 
  65     public String getSegmentName() {
  66         return segmentName;
  67     }
  68 
  69     public void setSegmentName(final String segmentName) {
  70         this.segmentName = segmentName;
  71     }
  72 
  73     public int getVmAddress() {
  74         return vmAddress;
  75     }
  76 
  77     public void setVmAddress(final int vmAddress) {
  78         this.vmAddress = vmAddress;
  79     }
  80 
  81     public int getVmSize() {
  82         return vmSize;
  83     }
  84 
  85     public void setVmSize(final int vmSize) {
  86         this.vmSize = vmSize;
  87     }
  88 
  89     public int getFileOffset() {
  90         return fileOffset;
  91     }
  92 
  93     public void setFileOffset(final int fileOffset) {
  94         this.fileOffset = fileOffset;
  95     }
  96 
  97     public int getFileSize() {
  98         return fileSize;
  99     }
 100 
 101     public void setFileSize(final int fileSize) {
 102         this.fileSize = fileSize;
 103     }
 104 
 105     public int getMaxVmProtection() {
 106         return maxVmProtection;
 107     }
 108 
 109     public void setMaxVmProtection(final int maxVmProtection) {
 110         this.maxVmProtection = maxVmProtection;
 111     }
 112 
 113     public int getInitVmProtection() {
 114         return initVmProtection;
 115     }
 116 
 117     public void setInitVmProtection(final int initVmProtection) {
 118         this.initVmProtection = initVmProtection;
 119     }
 120 
 121     public int getFlags() {
 122         return flags;
 123     }
 124 
 125     public void setFlags(final int flags) {
 126         this.flags = flags;
 127     }
 128 
 129     @Override
 130     public String toString() {
 131         return "SegmentCommand { segmentName: \"" + segmentName + "\""
 132                        + ", vmAddress: 0x" + Util.hex32(vmAddress)
 133                        + ", vmSize: 0x" + Util.hex32(vmSize)
 134                        + ", fileOffset: 0x" + Util.hex32(fileOffset)
 135                        + ", fileSize: 0x" + Util.hex32(fileSize)
 136                        + ", maxVmProtection: " + maxVmProtection
 137                        + ", initVmProtection: " + initVmProtection
 138                        + ", flags: 0x" + Util.hex32(flags)
 139                        + ", sections: " + sections + " }";
 140     }
 141 
 142     @Override
 143     protected int getPayloadSize() {
 144         return 16 + 4 * 8 + 68 * sections.size();
 145     }
 146 
 147     @Override
 148     protected void readPayload(final DataInput dataInput) throws IOException {
 149         segmentName = Util.readString(dataInput, 16).trim();
 150         vmAddress = dataInput.readInt();
 151         vmSize = dataInput.readInt();
 152         fileOffset = dataInput.readInt();
 153         fileSize = dataInput.readInt();
 154         maxVmProtection = dataInput.readInt();
 155         initVmProtection = dataInput.readInt();
 156         final int numberOfSections = dataInput.readInt();
 157         flags = dataInput.readInt();
 158 
 159         sections.clear();
 160         sections.ensureCapacity(numberOfSections);
 161         for (int i = 0; i < numberOfSections; ++i) {
 162             final Section section = new Section();
 163             section.readImpl(dataInput);
 164             sections.add(section);
 165         }
 166     }
 167 
 168     @Override
 169     protected void writePayload(final DataOutput dataOutput)
 170             throws IOException {
 171         Util.writeString(dataOutput, segmentName, 16, '\0');
 172         dataOutput.writeInt(vmAddress);
 173         dataOutput.writeInt(vmSize);
 174         dataOutput.writeInt(fileOffset);
 175         dataOutput.writeInt(fileSize);
 176         dataOutput.writeInt(maxVmProtection);
 177         dataOutput.writeInt(initVmProtection);
 178         dataOutput.writeInt(sections.size());
 179         dataOutput.writeInt(flags);
 180 
 181         for (final Section section: sections) {
 182             section.write(dataOutput);
 183         }
 184     }
 185 
 186     public static final class Section {
 187         private String sectionName;
 188         private String segmentName;
 189         private int address;
 190         private int size;
 191         private int offset;
 192         private int align;
 193         private int relocationOffset;
 194         private int numberOfRelocations;
 195         private int flags;
 196         private int reserved1;
 197         private int reserved2;
 198 
 199         public String getSectionName() {
 200             return sectionName;
 201         }
 202 
 203         public void setSectionName(final String sectionName) {
 204             this.sectionName = sectionName;
 205         }
 206 
 207         public String getSegmentName() {
 208             return segmentName;
 209         }
 210 
 211         public void setSegmentName(final String segmentName) {
 212             this.segmentName = segmentName;
 213         }
 214 
 215         public int getAddress() {
 216             return address;
 217         }
 218 
 219         public void setAddress(final int address) {
 220             this.address = address;
 221         }
 222 
 223         public int getSize() {
 224             return size;
 225         }
 226 
 227         public void setSize(final int size) {
 228             this.size = size;
 229         }
 230 
 231         public int getOffset() {
 232             return offset;
 233         }
 234 
 235         public void setOffset(final int offset) {
 236             this.offset = offset;
 237         }
 238 
 239         public int getAlign() {
 240             return align;
 241         }
 242 
 243         public void setAlign(final int align) {
 244             this.align = align;
 245         }
 246 
 247         public int getRelocationOffset() {
 248             return relocationOffset;
 249         }
 250 
 251         public void setRelocationOffset(final int relocationOffset) {
 252             this.relocationOffset = relocationOffset;
 253         }
 254 
 255         public int getNumberOfRelocations() {
 256             return numberOfRelocations;
 257         }
 258 
 259         public void setNumberOfRelocations(final int numberOfRelocations) {
 260             this.numberOfRelocations = numberOfRelocations;
 261         }
 262 
 263         public int getFlags() {
 264             return flags;
 265         }
 266 
 267         public void setFlags(final int flags) {
 268             this.flags = flags;
 269         }
 270 
 271         public int getReserved1() {
 272             return reserved1;
 273         }
 274 
 275         public void setReserved1(final int reserved1) {
 276             this.reserved1 = reserved1;
 277         }
 278 
 279         public int getReserved2() {
 280             return reserved2;
 281         }
 282 
 283         public void setReserved2(final int reserved2) {
 284             this.reserved2 = reserved2;
 285         }
 286 
 287         public void write(final DataOutput dataOutput) throws IOException {
 288             Util.writeString(dataOutput, sectionName, 16, '\0');
 289             Util.writeString(dataOutput, segmentName, 16, '\0');
 290             dataOutput.writeInt(address);
 291             dataOutput.writeInt(size);
 292             dataOutput.writeInt(offset);
 293             dataOutput.writeInt(align);
 294             dataOutput.writeInt(relocationOffset);
 295             dataOutput.writeInt(numberOfRelocations);
 296             dataOutput.writeInt(flags);
 297             dataOutput.writeInt(reserved1);
 298             dataOutput.writeInt(reserved2);
 299         }
 300 
 301         private void readImpl(final DataInput dataInput) throws IOException {
 302             sectionName = Util.readString(dataInput, 16).trim();
 303             segmentName = Util.readString(dataInput, 16).trim();
 304             address = dataInput.readInt();
 305             size = dataInput.readInt();
 306             offset = dataInput.readInt();
 307             align = dataInput.readInt();
 308             relocationOffset = dataInput.readInt();
 309             numberOfRelocations = dataInput.readInt();
 310             flags = dataInput.readInt();
 311             reserved1 = dataInput.readInt();
 312             reserved2 = dataInput.readInt();
 313         }
 314 
 315         @Override
 316         public String toString() {
 317             return "Section { sectionName: \"" + sectionName + "\""
 318                              + ", segmentName: \"" + segmentName + "\""
 319                              + ", address: 0x" + Util.hex32(address)
 320                              + ", size: 0x" + Util.hex32(size)
 321                              + ", offset: 0x" + Util.hex32(offset)
 322                              + ", align: " + align
 323                              + ", relocationOffset: 0x"
 324                                      + Util.hex32(relocationOffset)
 325                              + ", numberOfRelocations: " + numberOfRelocations
 326                              + ", flags: 0x" + Util.hex32(flags)
 327                              + ", reserved1: " + reserved1
 328                              + ", reserved2: " + reserved2 + " }";
 329         }
 330     }
 331 }