#!/usr/bin/python
#
# Copyright 2010 The Native Client Authors.  All rights reserved.  Use
# of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# This tool generates bad x86_64 NaCl modules that should never be
# generated by a conformant compiler.  These bad modules are used to
# test that sel_ldr correctly detects that these are bad modules.
#
# The detailed info about the fib_scalar.nexe used as input:
# $ readelf -l fib_scalar.nexe
#
# Elf file type is EXEC (Executable file)
# Entry point 0x20080
# There are 4 program headers, starting at offset 64
#
# Program Headers:
#   Type           Offset             VirtAddr           PhysAddr
#                  FileSiz            MemSiz              Flags  Align
#   PHDR           0x0000000000000000 0x0000000000000000 0x0000000000000000
#                  0x0000000000000120 0x0000000000000120  R      8
#   LOAD           0x0000000000020000 0x0000000000020000 0x0000000000020000
#                  0x00000000000277c0 0x00000000000277c0  R E    200000
#   LOAD           0x0000000000200000 0x0000000000200000 0x0000000000200000
#                  0x0000000000206054 0x0000000000206054  R      200000
#   LOAD           0x0000000000600000 0x0000000000600000 0x0000000000600000
#                  0x0000000000000994 0x0000000000001c68  RW     200000
#
#  Section to Segment mapping:
#   Segment Sections...
#    00
#    01     .init .text .fini
#    02     .rodata .nacl_rpc_methods .eh_frame_hdr .eh_frame .tdata .ctors .dtors .jcr
#    03     .data .bss

import sys

EHDR_SIZE=64
PHDR_SIZE=56
P_MEMSZ_OFF=(5*8)

FILE_MODIFICATIONS=[
## $ readelf -l data_not_last.nexe
## Program Headers:
##   Type           Offset             VirtAddr           PhysAddr
##                  FileSiz            MemSiz              Flags  Align
##   PHDR           0x0000000000000000 0x0000000000000000 0x0000000000000000
##                  0x0000000000000120 0x0000000000000120  R      8
##   LOAD           0x0000000000020000 0x0000000000020000 0x0000000000020000
##                  0x00000000000277a0 0x00000000500277a0  R E    200000
##   LOAD           0x0000000000200000 0x0000000000200000 0x0000000000200000
##                  0x0000000000206054 0x0000000000206054  R      200000
##   LOAD           0x0000000000600000 0x0000000000600000 0x0000000000600000
##                  0x0000000000000994 0x0000000000001c68  RW     200000
##  Section to Segment mapping:
##   Segment Sections...
##    00
##    01     .init .text .fini .bss
##    02     .rodata .nacl_rpc_methods .eh_frame_hdr .eh_frame .tdata .ctors .dtors .jcr
##    03     .data .bss
    [ "fib_scalar.nexe", "data_not_last.nexe",
      [ ( EHDR_SIZE + PHDR_SIZE + P_MEMSZ_OFF + 3, chr(0x50)),
        ]
      ],
## $ readelf -l negative_hole.nexe
## Program Headers:
##   Type           Offset             VirtAddr           PhysAddr
##                  FileSiz            MemSiz              Flags  Align
##   PHDR           0x0000000000000000 0x0000000000000000 0x0000000000000000
##                  0x0000000000000120 0x0000000000000120  R      8
##   LOAD           0x0000000000020000 0x0000000000020000 0x0000000000020000
##                  0x00000000000277a0 0x00000000000277a0  R E    200000
##   LOAD           0x0000000000200000 0x0000000000200000 0x0000000000200000
##                  0x0000000000206054 0x0000000000206054  R      200000
##   LOAD           0x0000000000600000 0x0000000000600000 0x0000000000600000
##                  0x0000000000000994 0x00000000ff9ffff0  RW     200000
##  Section to Segment mapping:
##   Segment Sections...
##    00
##    01     .init .text .fini
##    02     .rodata .nacl_rpc_methods .eh_frame_hdr .eh_frame .tdata .ctors .dtors .jcr
##    03     .data .bss
    [ "fib_scalar.nexe", "negative_hole.nexe",
      [ ( EHDR_SIZE + 3*PHDR_SIZE + P_MEMSZ_OFF + 3, chr(0xff)),
        ( EHDR_SIZE + 3*PHDR_SIZE + P_MEMSZ_OFF + 2, chr(0x9f)),
        ( EHDR_SIZE + 3*PHDR_SIZE + P_MEMSZ_OFF + 1, chr(0xff)),
        ( EHDR_SIZE + 3*PHDR_SIZE + P_MEMSZ_OFF + 0, chr(0xf0)),
        ],
      ],
## $ readelf -l rodata_data_overlap.nexe
## Program Headers:
##   Type           Offset             VirtAddr           PhysAddr
##                  FileSiz            MemSiz              Flags  Align
##   PHDR           0x0000000000000000 0x0000000000000000 0x0000000000000000
##                  0x0000000000000120 0x0000000000000120  R      8
##   LOAD           0x0000000000020000 0x0000000000020000 0x0000000000020000
##                  0x00000000000277a0 0x00000000000277a0  R E    200000
##   LOAD           0x0000000000200000 0x0000000000200000 0x0000000000200000
##                  0x0000000000206054 0x0000000000401054  R      200000
##   LOAD           0x0000000000600000 0x0000000000600000 0x0000000000600000
##                  0x0000000000000994 0x0000000000001c68  RW     200000
##  Section to Segment mapping:
##   Segment Sections...
##    00
##    01     .init .text .fini
##    02     .rodata .nacl_rpc_methods .eh_frame_hdr .eh_frame .tdata .ctors .dtors .jcr
##    03     .data .bss
    [ "fib_scalar.nexe", "rodata_data_overlap.nexe",
      [ ( EHDR_SIZE + 2*PHDR_SIZE + P_MEMSZ_OFF + 2, chr(0x40)),
        ( EHDR_SIZE + 2*PHDR_SIZE + P_MEMSZ_OFF + 1, chr(0x10)),
        ]
      ],
## $ readelf -l text_too_big.nexe
## Program Headers:
##   Type           Offset             VirtAddr           PhysAddr
##                  FileSiz            MemSiz              Flags  Align
##   PHDR           0x0000000000000000 0x0000000000000000 0x0000000000000000
##                  0x0000000000000120 0x0000000000000120  R      8
##   LOAD           0x0000000000020000 0x0000000000020000 0x0000000000020000
##                  0x00000000000277a0 0x000000f0000277a0  R E    200000
##   LOAD           0x0000000000200000 0x0000000000200000 0x0000000000200000
##                  0x0000000000206054 0x0000000000206054  R      200000
##   LOAD           0x0000000000600000 0x0000000000600000 0x0000000000600000
##                  0x0000000000000994 0x0000000000001c68  RW     200000
    [ "fib_scalar.nexe", "text_too_big.nexe",
      [ ( EHDR_SIZE + PHDR_SIZE + P_MEMSZ_OFF + 4, chr(0xf0)),
        ],
      ],
## $ readelf -l integer_overflow_while_madvising.nexe
## Program Headers:
##   Type           Offset             VirtAddr           PhysAddr
##                  FileSiz            MemSiz              Flags  Align
##   PHDR           0x0000000000000000 0x0000000000000000 0x0000000000000000
##                  0x0000000000000120 0x0000000000000120  R      8
##   LOAD           0x0000000000020000 0x0000000000020000 0x0000000000020000
##                  0x00000000000277a0 0x0000000f000277a0  R E    200000
##   LOAD           0x0000000000200000 0x0000000000200000 0x0000000000200000
##                  0x0000000000206054 0x0000000000206054  R      200000
##   LOAD           0x0000000000600000 0x0000000000600000 0x0000000000600000
##                  0x0000000000000994 0x0000000000001c68  RW     200000
    [ "fib_scalar.nexe", "integer_overflow_while_madvising.nexe",
      [ ( EHDR_SIZE + PHDR_SIZE + P_MEMSZ_OFF + 4, chr(0x0f)),
        ],
      ],
## $ readelf -l text_overlaps_data.nexe
## Program Headers:
##   Type           Offset             VirtAddr           PhysAddr
##                  FileSiz            MemSiz              Flags  Align
##   PHDR           0x0000000000000000 0x0000000000000000 0x0000000000000000
##                  0x0000000000000120 0x0000000000000120  R      8
##   LOAD           0x0000000000020000 0x0000000000020000 0x0000000000020000
##                  0x00000000000277a0 0x00000000005e10a0  R E    200000
##   LOAD           0x0000000000200000 0x0000000000200000 0x0000000000200000
##                  0x0000000000206054 0x0000000000206054  R      200000
##   LOAD           0x0000000000600000 0x0000000000600000 0x0000000000600000
##                  0x0000000000000994 0x0000000000001c68  RW     200000
    [ "fib_scalar.nexe", "text_overlaps_data.nexe",
      [ ( EHDR_SIZE + PHDR_SIZE + P_MEMSZ_OFF + 2, chr(0x5e)),
        ( EHDR_SIZE + PHDR_SIZE + P_MEMSZ_OFF + 1, chr(0x10)),
        ],
      ],
## $ readelf -l text_overlaps_rodata.nexe
## Program Headers:
##   Type           Offset             VirtAddr           PhysAddr
##                  FileSiz            MemSiz              Flags  Align
##   PHDR           0x0000000000000000 0x0000000000000000 0x0000000000000000
##                  0x0000000000000120 0x0000000000000120  R      8
##   LOAD           0x0000000000020000 0x0000000000020000 0x0000000000020000
##                  0x00000000000277a0 0x00000000002077a0  R E    200000
##   LOAD           0x0000000000200000 0x0000000000200000 0x0000000000200000
##                  0x0000000000206054 0x0000000000206054  R      200000
##   LOAD           0x0000000000600000 0x0000000000600000 0x0000000000600000
##                  0x0000000000000994 0x0000000000001c68  RW     200000
    [ "fib_scalar.nexe", "text_overlaps_rodata.nexe",
      [ ( EHDR_SIZE + PHDR_SIZE + P_MEMSZ_OFF + 2, chr(0x20)),
        ],
      ],
    ]

def UpdateData(data, change_list):
  for ix, replacement_byte in change_list:
    data = data[:ix] + replacement_byte + data[ix+1:]
  return data


def UpdateFileWithChangeList(src_file, dst_file, change_list):
  data = open(src_file).read()
  data = UpdateData(data, change_list)
  open(dst_file, 'w').write(data)

if __name__ == '__main__':
  for src_file, dst_file, cl in FILE_MODIFICATIONS:
    UpdateFileWithChangeList(src_file, dst_file, cl)
  sys.exit(0)
