~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to dyngen.c

  • Committer: bellard
  • Date: 2004-07-10 16:22:18 UTC
  • Revision ID: git-v1:82eec0a1740cead905de40fc9970cdc1ad2ea51b
Mac OS X port (Pierre d'Herbemont)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@999 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 *  The COFF object format support was extracted from Kazu's QEMU port
7
7
 *  to Win32.
8
8
 *
 
9
 *  Mach-O Support by Matt Reda and Pierre d'Herbemont
 
10
 *
9
11
 *  This program is free software; you can redistribute it and/or modify
10
12
 *  it under the terms of the GNU General Public License as published by
11
13
 *  the Free Software Foundation; either version 2 of the License, or
34
36
   compilation */
35
37
#if defined(CONFIG_WIN32)
36
38
#define CONFIG_FORMAT_COFF
 
39
#elif defined(CONFIG_DARWIN)
 
40
#define CONFIG_FORMAT_MACH
37
41
#else
38
42
#define CONFIG_FORMAT_ELF
39
43
#endif
169
173
 
170
174
#endif /* CONFIG_FORMAT_COFF */
171
175
 
 
176
#ifdef CONFIG_FORMAT_MACH
 
177
 
 
178
#include <mach-o/loader.h>
 
179
#include <mach-o/nlist.h>
 
180
#include <mach-o/reloc.h>
 
181
#include <mach-o/ppc/reloc.h>
 
182
 
 
183
# define check_mach_header(x) (x.magic == MH_MAGIC)
 
184
typedef int32_t host_long;
 
185
typedef uint32_t host_ulong;
 
186
 
 
187
struct nlist_extended
 
188
{
 
189
   union {
 
190
   char *n_name; 
 
191
   long  n_strx; 
 
192
   } n_un;
 
193
   unsigned char n_type; 
 
194
   unsigned char n_sect; 
 
195
   short st_desc;
 
196
   unsigned long st_value;
 
197
   unsigned long st_size;
 
198
};
 
199
 
 
200
#define EXE_RELOC struct relocation_info
 
201
#define EXE_SYM struct nlist_extended
 
202
 
 
203
#endif /* CONFIG_FORMAT_MACH */
 
204
 
172
205
#include "bswap.h"
173
206
 
174
207
enum {
399
432
    return 0;
400
433
}
401
434
 
 
435
static host_ulong get_rel_offset(EXE_RELOC *rel)
 
436
{
 
437
    return rel->r_offset;
 
438
}
 
439
 
402
440
static char *get_rel_sym_name(EXE_RELOC *rel)
403
441
{
404
442
    return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
600
638
    return name;
601
639
}
602
640
 
 
641
static host_ulong get_rel_offset(EXE_RELOC *rel)
 
642
{
 
643
    return rel->r_offset;
 
644
}
 
645
 
603
646
struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
604
647
{
605
648
    int i;
758
801
 
759
802
#endif /* CONFIG_FORMAT_COFF */
760
803
 
 
804
#ifdef CONFIG_FORMAT_MACH
 
805
 
 
806
/* File Header */
 
807
struct mach_header      mach_hdr;
 
808
 
 
809
/* commands */
 
810
struct segment_command  *segment = 0;
 
811
struct dysymtab_command *dysymtabcmd = 0;
 
812
struct symtab_command   *symtabcmd = 0;
 
813
 
 
814
/* section */
 
815
struct section  *section_hdr;
 
816
struct section *text_sec_hdr;
 
817
uint8_t         **sdata;
 
818
 
 
819
/* relocs */
 
820
struct relocation_info *relocs;
 
821
        
 
822
/* symbols */
 
823
EXE_SYM                 *symtab;
 
824
struct nlist    *symtab_std;
 
825
char                    *strtab;
 
826
 
 
827
/* indirect symbols */
 
828
uint32_t        *tocdylib;
 
829
 
 
830
/* Utility functions */
 
831
 
 
832
static inline char *find_str_by_index(int index)
 
833
{
 
834
    return strtab+index;
 
835
}
 
836
 
 
837
/* Used by dyngen common code */
 
838
static char *get_sym_name(EXE_SYM *sym)
 
839
{
 
840
        char *name = find_str_by_index(sym->n_un.n_strx);
 
841
        
 
842
        if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
 
843
                return "debug";
 
844
                        
 
845
        if(!name)
 
846
                return name;
 
847
        if(name[0]=='_')
 
848
                return name + 1;
 
849
        else
 
850
                return name;
 
851
}
 
852
 
 
853
/* find a section index given its segname, sectname */
 
854
static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname, 
 
855
                                  const char *sectname)
 
856
{
 
857
    int i;
 
858
    struct section *sec = section_hdr;
 
859
 
 
860
    for(i = 0; i < shnum; i++, sec++) {
 
861
        if (!sec->segname || !sec->sectname)
 
862
            continue;
 
863
        if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
 
864
            return i;
 
865
    }
 
866
    return -1;
 
867
}
 
868
 
 
869
/* find a section header given its segname, sectname */
 
870
struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname, 
 
871
                                  const char *sectname)
 
872
{
 
873
    int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
 
874
        if(index == -1)
 
875
                return NULL;
 
876
        return section_hdr+index;
 
877
}
 
878
 
 
879
 
 
880
static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
 
881
{
 
882
    struct scattered_relocation_info * scarel;
 
883
        
 
884
    if(R_SCATTERED & rel->r_address) {
 
885
        scarel = (struct scattered_relocation_info*)rel;
 
886
        if(scarel->r_type != PPC_RELOC_PAIR)
 
887
            error("fetch_next_pair_value: looking for a pair which was not found (1)");
 
888
        *value = scarel->r_value;
 
889
    } else {
 
890
                if(rel->r_type != PPC_RELOC_PAIR)
 
891
                        error("fetch_next_pair_value: looking for a pair which was not found (2)");
 
892
                *value = rel->r_address;
 
893
        }
 
894
}
 
895
 
 
896
/* find a sym name given its value, in a section number */
 
897
static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
 
898
{
 
899
        int i, ret = -1;
 
900
        
 
901
        for( i = 0 ; i < nb_syms; i++ )
 
902
        {
 
903
            if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
 
904
                         (symtab[i].n_sect ==  sectnum) && (symtab[i].st_value <= value) )
 
905
                {
 
906
                        if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
 
907
                                ret = i;
 
908
                }
 
909
        }
 
910
        if( ret < 0 ) {
 
911
                *offset = 0;
 
912
                return 0;
 
913
        } else {
 
914
                *offset = value - symtab[ret].st_value;
 
915
                return get_sym_name(&symtab[ret]);
 
916
        }
 
917
}
 
918
 
 
919
/* 
 
920
 *  Find symbol name given a (virtual) address, and a section which is of type 
 
921
 *  S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
 
922
 */
 
923
static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
 
924
{
 
925
    unsigned int tocindex, symindex, size;
 
926
    const char *name = 0;
 
927
    
 
928
    /* Sanity check */
 
929
    if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
 
930
        return (char*)0;
 
931
                
 
932
        if( sec_hdr->flags & S_SYMBOL_STUBS ){
 
933
                size = sec_hdr->reserved2;
 
934
                if(size == 0)
 
935
                    error("size = 0");
 
936
                
 
937
        }
 
938
        else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
 
939
                    sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
 
940
                size = sizeof(unsigned long);
 
941
        else
 
942
                return 0;
 
943
                
 
944
    /* Compute our index in toc */
 
945
        tocindex = (address - sec_hdr->addr)/size;
 
946
        symindex = tocdylib[sec_hdr->reserved1 + tocindex];
 
947
        
 
948
        name = get_sym_name(&symtab[symindex]);
 
949
 
 
950
    return name;
 
951
}
 
952
 
 
953
static const char * find_reloc_name_given_its_address(int address)
 
954
{
 
955
    unsigned int i;
 
956
    for(i = 0; i < segment->nsects ; i++)
 
957
    {
 
958
        const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
 
959
        if((long)name != -1)
 
960
            return name;
 
961
    }
 
962
    return 0;
 
963
}
 
964
 
 
965
static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
 
966
{
 
967
        char * name = 0;
 
968
        struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
 
969
        int sectnum = rel->r_symbolnum;
 
970
        int sectoffset;
 
971
        int other_half=0;
 
972
        
 
973
        /* init the slide value */
 
974
        *sslide = 0;
 
975
        
 
976
        if(R_SCATTERED & rel->r_address)
 
977
                return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
 
978
 
 
979
        if(rel->r_extern)
 
980
        {
 
981
                /* ignore debug sym */
 
982
                if ( symtab[rel->r_symbolnum].n_type & N_STAB ) 
 
983
                        return 0;
 
984
                return get_sym_name(&symtab[rel->r_symbolnum]);
 
985
        }
 
986
 
 
987
        /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
 
988
        sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff;
 
989
                        
 
990
        if(sectnum==0xffffff)
 
991
                return 0;
 
992
 
 
993
        /* Sanity Check */
 
994
        if(sectnum > segment->nsects)
 
995
                error("sectnum > segment->nsects");
 
996
 
 
997
        switch(rel->r_type)
 
998
        {
 
999
                case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset & 0xffff);
 
1000
                        break;
 
1001
                case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (other_half & 0xffff);
 
1002
                        break;
 
1003
                case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (other_half & 0xffff);
 
1004
                        break;
 
1005
                case PPC_RELOC_BR24:
 
1006
                        sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
 
1007
                        if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
 
1008
                        break;
 
1009
                default:
 
1010
                        error("switch(rel->type) not found");
 
1011
        }
 
1012
 
 
1013
        if(rel->r_pcrel)
 
1014
                sectoffset += rel->r_address;
 
1015
                        
 
1016
        if (rel->r_type == PPC_RELOC_BR24)
 
1017
                name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
 
1018
 
 
1019
        /* search it in the full symbol list, if not found */
 
1020
        if(!name)
 
1021
                name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
 
1022
        
 
1023
        return name;
 
1024
}
 
1025
 
 
1026
/* Used by dyngen common code */
 
1027
static const char * get_rel_sym_name(EXE_RELOC * rel)
 
1028
{
 
1029
        int sslide;
 
1030
        return get_reloc_name( rel, &sslide);
 
1031
}
 
1032
 
 
1033
/* Used by dyngen common code */
 
1034
static host_ulong get_rel_offset(EXE_RELOC *rel)
 
1035
{
 
1036
        struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
 
1037
    if(R_SCATTERED & rel->r_address)
 
1038
                return sca_rel->r_address;
 
1039
        else
 
1040
                return rel->r_address;
 
1041
}
 
1042
 
 
1043
/* load a mach-o object file */
 
1044
int load_object(const char *filename)
 
1045
{
 
1046
        int fd;
 
1047
        unsigned int offset_to_segment = 0;
 
1048
    unsigned int offset_to_dysymtab = 0;
 
1049
    unsigned int offset_to_symtab = 0;
 
1050
    struct load_command lc;
 
1051
    unsigned int i, j;
 
1052
        EXE_SYM *sym;
 
1053
        struct nlist *syment;
 
1054
    
 
1055
        fd = open(filename, O_RDONLY);
 
1056
    if (fd < 0) 
 
1057
        error("can't open file '%s'", filename);
 
1058
                
 
1059
    /* Read Mach header.  */
 
1060
    if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
 
1061
        error("unable to read file header");
 
1062
 
 
1063
    /* Check Mach identification.  */
 
1064
    if (!check_mach_header(mach_hdr)) {
 
1065
        error("bad Mach header");
 
1066
    }
 
1067
    
 
1068
    if (mach_hdr.cputype != CPU_TYPE_POWERPC)
 
1069
        error("Unsupported CPU");
 
1070
        
 
1071
    if (mach_hdr.filetype != MH_OBJECT)
 
1072
        error("Unsupported Mach Object");
 
1073
    
 
1074
    /* read segment headers */
 
1075
    for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
 
1076
    {
 
1077
        if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command))
 
1078
            error("unable to read load_command");
 
1079
        if(lc.cmd == LC_SEGMENT)
 
1080
        {
 
1081
            offset_to_segment = j;
 
1082
            lseek(fd, offset_to_segment, SEEK_SET);
 
1083
            segment = malloc(sizeof(struct segment_command));
 
1084
            if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command))
 
1085
                error("unable to read LC_SEGMENT");
 
1086
        }
 
1087
        if(lc.cmd == LC_DYSYMTAB)
 
1088
        {
 
1089
            offset_to_dysymtab = j;
 
1090
            lseek(fd, offset_to_dysymtab, SEEK_SET);
 
1091
            dysymtabcmd = malloc(sizeof(struct dysymtab_command));
 
1092
            if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command))
 
1093
                error("unable to read LC_DYSYMTAB");
 
1094
        }
 
1095
        if(lc.cmd == LC_SYMTAB)
 
1096
        {
 
1097
            offset_to_symtab = j;
 
1098
            lseek(fd, offset_to_symtab, SEEK_SET);
 
1099
            symtabcmd = malloc(sizeof(struct symtab_command));
 
1100
            if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command))
 
1101
                error("unable to read LC_SYMTAB");
 
1102
        }
 
1103
        j+=lc.cmdsize;
 
1104
 
 
1105
        lseek(fd, j, SEEK_SET);
 
1106
    }
 
1107
 
 
1108
    if(!segment)
 
1109
        error("unable to find LC_SEGMENT");
 
1110
 
 
1111
    /* read section headers */
 
1112
    section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
 
1113
 
 
1114
    /* read all section data */
 
1115
    sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
 
1116
    memset(sdata, 0, sizeof(void *) * segment->nsects);
 
1117
    
 
1118
        /* Load the data in section data */
 
1119
        for(i = 0; i < segment->nsects; i++) {
 
1120
        sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
 
1121
    }
 
1122
        
 
1123
    /* text section */
 
1124
        text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
 
1125
        i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
 
1126
        if (i == -1 || !text_sec_hdr)
 
1127
        error("could not find __TEXT,__text section");
 
1128
    text = sdata[i];
 
1129
        
 
1130
    /* Make sure dysym was loaded */
 
1131
    if(!(int)dysymtabcmd)
 
1132
        error("could not find __DYSYMTAB segment");
 
1133
    
 
1134
    /* read the table of content of the indirect sym */
 
1135
    tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
 
1136
    
 
1137
    /* Make sure symtab was loaded  */
 
1138
    if(!(int)symtabcmd)
 
1139
        error("could not find __SYMTAB segment");
 
1140
    nb_syms = symtabcmd->nsyms;
 
1141
 
 
1142
    symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
 
1143
    strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
 
1144
        
 
1145
        symtab = malloc(sizeof(EXE_SYM) * nb_syms);
 
1146
        
 
1147
        /* Now transform the symtab, to an extended version, with the sym size, and the C name */
 
1148
        for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
 
1149
        const char *name;
 
1150
        struct nlist *sym_follow, *sym_next = 0;
 
1151
        unsigned int j;
 
1152
        name = find_str_by_index(sym->n_un.n_strx);
 
1153
                memset(sym, 0, sizeof(*sym));
 
1154
                
 
1155
                if ( sym->n_type & N_STAB ) /* Debug symbols are skipped */
 
1156
            continue;
 
1157
                        
 
1158
                memcpy(sym, syment, sizeof(*syment));
 
1159
                        
 
1160
                /* Find the following symbol in order to get the current symbol size */
 
1161
        for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) {
 
1162
            if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
 
1163
                continue;
 
1164
            if(!sym_next) {
 
1165
                sym_next = sym_follow;
 
1166
                continue;
 
1167
            }
 
1168
            if(!(sym_next->n_value > sym_follow->n_value))
 
1169
                continue;
 
1170
            sym_next = sym_follow;
 
1171
        }
 
1172
                if(sym_next)
 
1173
            sym->st_size = sym_next->n_value - sym->st_value;
 
1174
                else
 
1175
            sym->st_size = text_sec_hdr->size - sym->st_value;
 
1176
        }
 
1177
        
 
1178
    /* Find Reloc */
 
1179
    relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
 
1180
    nb_relocs = text_sec_hdr->nreloc;
 
1181
 
 
1182
        close(fd);
 
1183
        return 0;
 
1184
}
 
1185
 
 
1186
#endif /* CONFIG_FORMAT_MACH */
 
1187
 
761
1188
#ifdef HOST_ARM
762
1189
 
763
1190
int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1049
1476
        args_present[i] = 0;
1050
1477
 
1051
1478
    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1052
 
        if (rel->r_offset >= start_offset &&
1053
 
            rel->r_offset < start_offset + (p_end - p_start)) {
 
1479
        host_ulong offset = get_rel_offset(rel);
 
1480
        if (offset >= start_offset &&
 
1481
            offset < start_offset + (p_end - p_start)) {
1054
1482
            sym_name = get_rel_sym_name(rel);
 
1483
            if(!sym_name)
 
1484
                continue;
1055
1485
            if (strstart(sym_name, "__op_param", &p)) {
1056
1486
                n = strtoul(p, NULL, 10);
1057
1487
                if (n > MAX_ARGS)
1087
1517
        fprintf(outfile, "    extern void %s();\n", name);
1088
1518
 
1089
1519
        for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1090
 
            if (rel->r_offset >= start_offset &&
1091
 
                rel->r_offset < start_offset + (p_end - p_start)) {
 
1520
            host_ulong offset = get_rel_offset(rel);
 
1521
            if (offset >= start_offset &&
 
1522
                offset < start_offset + (p_end - p_start)) {
1092
1523
                sym_name = get_rel_sym_name(rel);
 
1524
                if(!sym_name)
 
1525
                    continue;
1093
1526
                if (*sym_name && 
1094
1527
                    !strstart(sym_name, "__op_param", NULL) &&
1095
1528
                    !strstart(sym_name, "__op_jmp", NULL)) {
1101
1534
                        continue;
1102
1535
                    }
1103
1536
#endif
 
1537
#ifdef __APPLE__
 
1538
/* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
 
1539
                    fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name);
 
1540
#else
1104
1541
                    fprintf(outfile, "extern char %s;\n", sym_name);
 
1542
#endif
1105
1543
                }
1106
1544
            }
1107
1545
        }
1108
1546
 
1109
 
        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n", name, start_offset - offset, copy_size);
 
1547
        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
 
1548
                                        name, (int)(start_offset - offset), copy_size);
1110
1549
 
1111
1550
        /* emit code offset information */
1112
1551
        {
1131
1570
                    } else {
1132
1571
                        ptr = NULL;
1133
1572
                    }
 
1573
#elif defined(CONFIG_FORMAT_MACH)
 
1574
                    if(!sym->n_sect)
 
1575
                        continue;
 
1576
                    ptr = sdata[sym->n_sect-1];
1134
1577
#else
1135
1578
                    ptr = sdata[sym->st_shndx];
1136
1579
#endif
1137
1580
                    if (!ptr)
1138
1581
                        error("__op_labelN in invalid section");
1139
1582
                    offset = sym->st_value;
 
1583
#ifdef CONFIG_FORMAT_MACH
 
1584
                    offset -= section_hdr[sym->n_sect-1].addr;
 
1585
#endif
1140
1586
                    val = *(unsigned long *)(ptr + offset);
1141
1587
#ifdef ELF_USES_RELOCA
1142
1588
                    {
1284
1730
            }
1285
1731
#elif defined(HOST_PPC)
1286
1732
            {
 
1733
#ifdef CONFIG_FORMAT_ELF
1287
1734
                char name[256];
1288
1735
                int type;
1289
1736
                int addend;
1337
1784
                        }
1338
1785
                    }
1339
1786
                }
 
1787
#elif defined(CONFIG_FORMAT_MACH)
 
1788
                                struct scattered_relocation_info *scarel;
 
1789
                                struct relocation_info * rel;
 
1790
                                char final_sym_name[256];
 
1791
                                const char *sym_name;
 
1792
                                const char *p;
 
1793
                                int slide, sslide;
 
1794
                                int i;
 
1795
        
 
1796
                                for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
 
1797
                                        unsigned int offset, length, value = 0;
 
1798
                                        unsigned int type, pcrel, isym = 0;
 
1799
                                        unsigned int usesym = 0;
 
1800
                                
 
1801
                                        if(R_SCATTERED & rel->r_address) {
 
1802
                                                scarel = (struct scattered_relocation_info*)rel;
 
1803
                                                offset = (unsigned int)scarel->r_address;
 
1804
                                                length = scarel->r_length;
 
1805
                                                pcrel = scarel->r_pcrel;
 
1806
                                                type = scarel->r_type;
 
1807
                                                value = scarel->r_value;
 
1808
                                        } else {
 
1809
                                                value = isym = rel->r_symbolnum;
 
1810
                                                usesym = (rel->r_extern);
 
1811
                                                offset = rel->r_address;
 
1812
                                                length = rel->r_length;
 
1813
                                                pcrel = rel->r_pcrel;
 
1814
                                                type = rel->r_type;
 
1815
                                        }
 
1816
                                
 
1817
                                        slide = offset - start_offset;
 
1818
                
 
1819
                                        if (!(offset >= start_offset && offset < start_offset + size)) 
 
1820
                                                continue;  /* not in our range */
 
1821
 
 
1822
                                        sym_name = get_reloc_name(rel, &sslide);
 
1823
                                        
 
1824
                                        if(usesym && symtab[isym].n_type & N_STAB)
 
1825
                                                continue; /* don't handle STAB (debug sym) */
 
1826
                                        
 
1827
                                        if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
 
1828
                                                int n;
 
1829
                                                n = strtol(p, NULL, 10);
 
1830
                                                fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
 
1831
                                                        n, slide);
 
1832
                                                continue; /* Nothing more to do */
 
1833
                                        }
 
1834
                                        
 
1835
                                        if(!sym_name)
 
1836
                                        {
 
1837
                                                fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
 
1838
                                                           name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
 
1839
                                                continue; /* dunno how to handle without final_sym_name */
 
1840
                                        }
 
1841
                                                                                                           
 
1842
                                        if (strstart(sym_name, "__op_param", &p)) {
 
1843
                                                snprintf(final_sym_name, sizeof(final_sym_name), "param%s", p);
 
1844
                                        } else {
 
1845
                                                snprintf(final_sym_name, sizeof(final_sym_name), "(long)(&%s)", sym_name);
 
1846
                                        }
 
1847
                        
 
1848
                                        switch(type) {
 
1849
                                        case PPC_RELOC_BR24:
 
1850
                                                fprintf(outfile, "{\n");
 
1851
                                                fprintf(outfile, "    uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
 
1852
                                                fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)gen_code_ptr) + %d) & 0x03fffffc);\n", 
 
1853
                                                                                        slide, slide, name, sslide );
 
1854
                                                fprintf(outfile, "}\n");
 
1855
                                                break;
 
1856
                                        case PPC_RELOC_HI16:
 
1857
                                                fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n", 
 
1858
                                                        slide, final_sym_name, sslide);
 
1859
                                                break;
 
1860
                                        case PPC_RELOC_LO16:
 
1861
                                                fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n", 
 
1862
                                        slide, final_sym_name, sslide);
 
1863
                            break;
 
1864
                                        case PPC_RELOC_HA16:
 
1865
                                                fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n", 
 
1866
                                                        slide, final_sym_name, sslide);
 
1867
                                                break;
 
1868
                                default:
 
1869
                                        error("unsupported powerpc relocation (%d)", type);
 
1870
                                }
 
1871
                        }
 
1872
#else
 
1873
#error unsupport object format
 
1874
#endif
1340
1875
            }
1341
1876
#elif defined(HOST_S390)
1342
1877
            {
1689
2224
        fprintf(outfile, "DEF(nop2, 2, 0)\n");
1690
2225
        fprintf(outfile, "DEF(nop3, 3, 0)\n");
1691
2226
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1692
 
            const char *name, *p;
 
2227
            const char *name;
1693
2228
            name = get_sym_name(sym);
1694
 
            if (strstart(name, OP_PREFIX, &p)) {
 
2229
            if (strstart(name, OP_PREFIX, NULL)) {
1695
2230
                gen_code(name, sym->st_value, sym->st_size, outfile, 2);
1696
2231
            }
1697
2232
        }
1702
2237
            const char *name;
1703
2238
            name = get_sym_name(sym);
1704
2239
            if (strstart(name, OP_PREFIX, NULL)) {
 
2240
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
1705
2241
                if (sym->st_shndx != text_shndx)
1706
2242
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
 
2243
#endif
1707
2244
                gen_code(name, sym->st_value, sym->st_size, outfile, 0);
1708
2245
            }
1709
2246
        }
1747
2284
                printf("%4d: %s pos=0x%08x len=%d\n", 
1748
2285
                       i, name, sym->st_value, sym->st_size);
1749
2286
#endif
 
2287
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
1750
2288
                if (sym->st_shndx != text_shndx)
1751
2289
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
 
2290
#endif
1752
2291
                gen_code(name, sym->st_value, sym->st_size, outfile, 1);
1753
2292
            }
1754
2293
        }