Difference in alignment of objects between MIPS and x86_64

I have a binary object that was generated on a 64-bit SGI machine using the MIPSpro compiler. I am trying to read this binary on a x86_64 64-bit machine with RHEL 6.7. The structure of the object is similar to

class A {
  public:
    A(){
      a_ = 1;
    }
    A(int a){
      a_ = a;
    }
    virtual ~A();
  protected:
    int a_;
};
class B : public A {
  public:
   // Constructors, methods, etc
    B(double b, int a){ 
      b_ = b;
      a_ = a;
    }
    virtual ~B();
  private:
    double b_;
};
A::~A(){}
B::~B(){}

After reading the binary file, byte swapping (due to the nature), I found that it was bcorrect, but aincorrect, which indicates data inconsistency with my current assembly.

I have two questions. First, how does the MIPS Pro compiler align its fields and how does it differ from the way gcc. I am interested in the case of inherited classes. Secondly, is there an option in gccor C ++ that can cause the alignment to be the same as the MIPS method?

1: MIPS ABI n64. ++, MIPS. x86_64.

2: sizeof virtual .
MIPS x86_64

size of class A: 4
size of class B: 16

virtual SGI MIPS

size of class A: 8
size of class B: 16

x86-64 Linux:

size of class A: 16
size of class B: 24

, ( ?). , ?

+4
2

, , ( , t , fwrite/fread - vtable - "" , ).

, , , " "; .

; , offsetof MIPS .

, , . , , , A :

  • 0x00: vptr (8 );
  • 0x08: a_ (4 );
  • 0x0c: (padding) (4 )

B :

  • 0x00: vptr (8 );
  • 0x08: A::a_ (4 );
  • 0x0c: (padding) (4 );
  • 0x10: b_ (8 ).

, . :

typedef unsigned char byte;

uint32_t read_u32_be(const byte *buf) {
    return uint32_t(buf[0])<<24 |
           uint32_t(buf[1])<<16 |
           uint32_t(buf[2])<<8  |
           uint32_t(buf[3]);
}

int32_t read_i32_be(const byte *buf) {
    // assume 2 complement in unsigned -> signed conversion
    return read_u32_be(buf);
}

double read_f64_be(const byte *buf) {
    static_assert(sizeof(double)==8);
    double ret;
    std::reverse_copy(buf, buf+8, (byte*)&ret);
    return ret;
}

void read_A(const byte *buf, A& t) {
    t.a_ = read_i32_be(buf+8);
}

void read_B(const uint8_t *buf, B& t) {
    read_A(buf, t);
    t.b_ = read_f64_be(buf+0x10);
}

, , MIPS, , - , .

BTW, , , ; , , ( - ).

+7

:

.
.
, .

, endianess.

+1

Source: https://habr.com/ru/post/1694927/


All Articles