| /* |
| * Copyright (c) 2019 The Regents of the University of California |
| * All rights reserved |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer; |
| * redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution; |
| * neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * Authors: Bobby R. Bruce |
| */ |
| |
| |
| #include <gtest/gtest.h> |
| |
| #include "base/loader/exec_ecoff.h" |
| |
| #define OMAGIC_STRUCT (*((const ecoff_exechdr *)omagic)) |
| #define NMAGIC_STRUCT (*((const ecoff_exechdr *)nmagic)) |
| #define ZMAGIC_STRUCT (*((const ecoff_exechdr *)zmagic)) |
| #define NO_MAGIC_STRUCT (*((const ecoff_exechdr *)no_magic)) |
| |
| #if (defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN))\ |
| && BYTE_ORDER==BIG_ENDIAN |
| const uint8_t zmagic[] = { |
| // ecoff_filehdr |
| 0x01, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| |
| // ecoff_aouthdr |
| 0x01, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
| }; |
| |
| const uint8_t nmagic[] = { |
| //ecoff_filehdr |
| 0x01, 0x08, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, |
| |
| //ecoff_aouthdr |
| 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
| }; |
| |
| const uint8_t omagic[] = { |
| //ecoff_filehdr |
| 0x01, 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| |
| //ecoff_aouthdr |
| 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
| }; |
| #elif defined(_LITTLE_ENDIAN) || BYTE_ORDER==LITTLE_ENDIAN |
| const uint8_t zmagic[] = { |
| // ecoff_filehdr |
| 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| |
| // ecoff_aouthdr |
| 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
| }; |
| |
| const uint8_t nmagic[] = { |
| //ecoff_filehdr |
| 0x08, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, |
| |
| //ecoff_aouthdr |
| 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
| }; |
| |
| const uint8_t omagic[] = { |
| //ecoff_filehdr |
| 0x07, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| |
| //ecoff_aouthdr |
| 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
| }; |
| #else |
| #error Invalid Endianess |
| #endif |
| |
| |
| |
| TEST(ExecEcoffTest, Round) |
| { |
| /* |
| * Note: ECOFF_ROUND always rounds up. |
| */ |
| EXPECT_EQ((1 << 10) + (1 << 8) + (1 << 6), |
| ECOFF_ROUND((1 << 10) + (1 << 8) + (1 << 5) + (1 << 4) + (1 << 1), |
| (1 << 5))); |
| |
| EXPECT_EQ((1 << 10) + (1 << 8) + (1 << 5), |
| ECOFF_ROUND((1 << 10) + (1 << 8) + (1 << 4) + (1 << 1), |
| (1 << 5))); |
| |
| EXPECT_EQ((1 << 10) + (1 << 8) + (1 << 6), |
| ECOFF_ROUND((1 << 10) + (1 << 8) + (1 << 5) + (1 << 1), |
| (1 << 5))); |
| } |
| |
| TEST(ExecEcoffTest, NoRounding) |
| { |
| EXPECT_EQ((1 << 10) + (1 << 8) + (1 << 5), |
| ECOFF_ROUND((1 << 10) + (1 << 8) + (1 << 5), |
| (1 << 5))); |
| } |
| |
| TEST(ExecEcoffTest, BlockAlignWithoutZmagic) |
| { |
| /* |
| * ECOFF_BLOCK_ALIGN will return "value" if "ep->a.magic" is not |
| * ECOFF_ZMAGIC. |
| */ |
| u_int64_t value = 0XFFFF; |
| |
| EXPECT_EQ(value, ECOFF_BLOCK_ALIGN(&OMAGIC_STRUCT, value)); |
| EXPECT_EQ(value, ECOFF_BLOCK_ALIGN(&OMAGIC_STRUCT, value)); |
| } |
| |
| TEST(ExecEcoffTest, BlockAlignWithZmagic) |
| { |
| /* |
| * ECOFF_BLOCK_ALIGN will return "value" rounded ECOFF_LDPGSZ (1 << 12) |
| * if "ep->a.magic" is ECOFF_ZMAGIC. This uses ECOFF_ROUND, so will only |
| * round up. |
| */ |
| u_int64_t value1 = (1 << 14) + (1 << 13) + (1 << 10) + (1 << 8); |
| u_int64_t expected_output1 = (1 << 14) + (1 << 13) + (1 << 12); |
| EXPECT_EQ(expected_output1, ECOFF_BLOCK_ALIGN(&ZMAGIC_STRUCT, value1)); |
| |
| u_int64_t value2 = (1 << 10) + (1 << 8); |
| u_int64_t expected_output2 = (1 << 12) ; |
| EXPECT_EQ(expected_output2, ECOFF_BLOCK_ALIGN(&ZMAGIC_STRUCT, value2)); |
| } |
| |
| TEST(ExecEcoffTest, SegmentAlignWithZmagic) |
| { |
| /* |
| * ECOFF_SEGMENT_ALIGN will round "value" rounded by ECOFF_LDPGZ (1 << 12) |
| * if "ep->amagic" is ECOFF_ZMAGIC. |
| */ |
| u_int64_t value1 = (1 << 14) + (1 << 13) + (1 << 10) + (1 << 8); |
| u_int64_t expected_output1 = (1 << 14) + (1 << 13) + (1 << 12); |
| EXPECT_EQ(expected_output1, ECOFF_SEGMENT_ALIGN(&ZMAGIC_STRUCT, value1)); |
| |
| u_int64_t value2 = (1 << 10) + (1 << 8); |
| u_int64_t expected_output2 = (1 << 12) ; |
| EXPECT_EQ(expected_output2, ECOFF_SEGMENT_ALIGN(&ZMAGIC_STRUCT, value2)); |
| } |
| |
| TEST(ExecEcoffTest, SegmentAlignWithoutZmagic) |
| { |
| /* |
| * ECOFF_SEGMENT_ALIGN will return value rounded by the |
| * ECOFF_SEGMENT_ALIGNMENT of ep (ECOFF_SEGMENT_ALIGNMENT is defined in |
| * "arch/alpha/ecoff_machdep.h") if "ep->amagic" is not ECOFF_ZMAGIC. |
| * |
| * ECOFF_SEGMENT_ALIGNMENT(ep) will return 8 if the 2nd LSB in |
| * "(ep)->f.f_flags" is 0 and 16 if it is 1. |
| * |
| * "(nmagic)->f.f_flags" is 0x2, and therefore ECOFF_SEGMENT_ALIGN will |
| * round value by (1 << 4). "(omagic)->f.f_flags" is 0x0 and, in this |
| * case, ECOFF_SEGMENT_ALIGN will round value by (1 << 3). |
| */ |
| |
| u_int64_t value = (1 << 14) + (1 << 13) + (1 << 8) + (1 << 4) + (1 << 2) |
| + (1 << 1); |
| |
| EXPECT_EQ((1 << 14) + (1 << 13) + (1 << 8) + (1 << 5), |
| ECOFF_SEGMENT_ALIGN(&NMAGIC_STRUCT, value)); // Round by (1 << 4). |
| EXPECT_EQ((1 << 14) + (1 << 13) + (1 << 8) + (1 << 4) + (1 << 3), |
| ECOFF_SEGMENT_ALIGN(&OMAGIC_STRUCT, value)); // Round by (1 << 3). |
| } |
| |
| TEST(ExecEcoffTest, TxtOffWithMagic) |
| { |
| /* |
| * ECOFF_TXTOFF will return 0 if "(ep)->a.magic" is ECOFF_ZMAGIC |
| */ |
| EXPECT_EQ(0, ECOFF_TXTOFF(&ZMAGIC_STRUCT)); |
| } |
| |
| TEST(ExecEcoffTest, TxtOffWithoutMagic) |
| { |
| /* |
| * If "(ep)->a.magic" is not ECOFF_ZMAGIC, ECOFF_TXTOFF will return |
| * "(ep)->f.f_nscns" multiplied by ECOFF_HDR_SIZE (sizeof ecoff_scnhdr) |
| * plus the size of ecoff_exechdr, roundeded by ECOFF_SEGMENT_ALIGNMENT. |
| * The value of ECOFF_SEGMENT_ALIGNMENT will return (1 << 3) if the 2nd |
| * LSB in "(ep)->f.f_flags" is 0 and (1 << 4) if it's one. |
| * |
| * In our setup (omagic)->f.f_flags is 0x0 and (nmagic)->f.f_flags is 0x2. |
| * (omagic)->f.f_nscns is 0xA, and (nmagic)->f.f_nscns is 0xF. |
| */ |
| |
| /* |
| * (sizeof omagic) * 0xA + (sizeof omagic), rounded by (1 << 3). |
| */ |
| u_int64_t expected_output_omagic = ECOFF_ROUND( |
| (sizeof(struct ecoff_scnhdr)) * 0xA |
| + (sizeof(struct ecoff_exechdr)), |
| (1 << 3)); |
| EXPECT_EQ(expected_output_omagic, ECOFF_TXTOFF(&OMAGIC_STRUCT)); |
| |
| /* |
| * (sizeof nmagic) * 0xF + (sizeof nmagic), rounded by (1 << 4). |
| */ |
| u_int64_t expected_output_nmagic = ECOFF_ROUND( |
| (sizeof(struct ecoff_scnhdr) * 0xF |
| + (sizeof(struct ecoff_exechdr))), |
| (1 << 4)); |
| EXPECT_EQ(expected_output_nmagic, ECOFF_TXTOFF(&NMAGIC_STRUCT)); |
| } |
| |
| TEST(ExecEcoffTest, DatOffWithMagic) |
| { |
| /* |
| * f (ep)->a.magic is ECOFF_ZMAGIC, ECOFF_DATOFF will return |
| * (ep)->a.tsize plus ECOFF_TXT(ep), rounded by ECOFF_LDPGSZ (1 << 12). |
| * |
| * (zmagic)->a.tsize is 0xF. |
| */ |
| |
| u_int64_t expected_output = ECOFF_ROUND( |
| 0xF + ECOFF_TXTOFF(&ZMAGIC_STRUCT), (1 << 12)); |
| EXPECT_EQ(expected_output, ECOFF_DATOFF(&ZMAGIC_STRUCT)); |
| } |
| |
| TEST(ExecEcoffTest, DatOffWithoutMagic) |
| { |
| /* |
| * ECOFF_DATOFF will return (ep)->a.tsize plus ECOFF_TXTOFF(ep) if |
| * (ep)->a.magic is not ECOFF_ZMAGIC. |
| * |
| * (nmagic)->a.tsize is 0xA. |
| * (omagic)->a.tsize is 0x1. |
| */ |
| |
| u_int64_t expected_output_nmagic = 0xA + ECOFF_TXTOFF(&NMAGIC_STRUCT); |
| EXPECT_EQ(expected_output_nmagic, ECOFF_DATOFF(&NMAGIC_STRUCT)); |
| |
| u_int64_t expected_output_omagic = 0x1 + ECOFF_TXTOFF(&OMAGIC_STRUCT); |
| EXPECT_EQ(expected_output_omagic, ECOFF_DATOFF(&OMAGIC_STRUCT)); |
| } |