/* -------------------------------------------------------------
* assembler.c
* FM 1er avril 2003
*
* Apres la phase d'analyse syntaxique minimale realisee
* par Analyse(), verifications contextuelles et production
* du fichier objet au format ELF
*
* Fournit la fonction main
* -------------------------------------------------------------
*/
#include <stdio.h>
#include "AA.h"
#include "AnalyseSynt.h"
#include "importelf.h"
#include <fcntl.h>
#include <stdlib.h>
#include <elf.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
/*#include <string.h>
#include <errno.h>*/
/* Tables pour VerifInst
* -----------------------
*/
static char *tableNomsRegs32 [] = {
"%eax",
"%ecx",
"%edx",
"%ebx",
"%esp",
"%ebp",
"%esi",
"%edi",
" "
} ;
static char *tableNomsRegs16 [] = {
"%ax",
"%cx",
"%dx",
"%bx",
"%sp",
"%bp",
"%si",
"%di",
" "
} ;
static char *tableNomsRegs8 [] = {
"%al",
"%cl",
"%dl",
"%bl",
"%ah",
"%ch",
"%dh",
"%bh",
" "
} ;
static char *tableInstructions2ParB [] = {
"addb",
"andb",
"cmpb",
"movb",
"orb",
"subb",
"xorb",
" "
} ;
static char *tableInstructions2ParW [] = {
"addw",
"andw",
"cmpw",
"movw",
"orw",
"subw",
"xorw",
" "
} ;
static char *tableInstructions2ParL [] = {
"addl",
"andl",
"cmpl",
"movl",
"orl",
"subl",
"xorl",
" "
} ;
static char *tableSautCond [] = {
"ja",
"jae",
"jb",
"jbe",
"je",
"jg",
"jge",
"jl",
"jle",
"jne",
" "
} ;
/* Types pour ELF
* --------------
*/
typedef struct {
Elf_Scn *TextSection ;
Elf_Scn *DataSection ;
Elf_Scn *BssSection ;
Elf_Scn *SymbolTable ;
Elf_Scn *StringTable ;
Elf_Scn *RelocTextSection ;
Elf_Scn *RelocDataSection ;
} SectionDescriptors ;
typedef struct {
int TextNameIndex ;
int DataNameIndex ;
int BssNameIndex ;
int SymbolTableNameIndex ;
int StringTableNameIndex ;
int RelocTextNameIndex ;
int RelocDataNameIndex ;
} NameIndexes ;
/* Pre-declarations des procedures et fonctions
* --------------------------------------------
*/
static int Verif (Elem *, int) ;
static void Decoration (Elem *, int) ;
static void Remplir_Listing (Elem *, int, FILE *) ;
static void GenererObjet (Elf *) ;
static void GenerateHeader (Elf *, SectionDescriptors *, NameIndexes *) ;
static void CreateTableOfSectionNames (Elf *, NameIndexes *) ;
static void GenerateTextAndReloc (Elf *, Elf_Scn *, Elf_Scn *, int , int );
static void GenerateTextAndReloc
(Elf *, Elf_Scn *, Elf_Scn *, int , int );
static void GenerateDataAndReloc
(Elf *, Elf_Scn *, Elf_Scn *, int , int ) ;
static void GenerateBss (Elf *, Elf_Scn *, int ) ;
static void GenerateSymbTab (Elf *, Elf_Scn *, int ) ;
static void GenerateCharTab (Elf *, Elf_Scn *, int ) ;
static void SetSHDR ( Elf32_Shdr *shdr,
Elf32_Word sh_name, /* section name */
Elf32_Word sh_type, /* SH_... */
Elf32_Word sh_flags, /* SHF_... */
Elf32_Addr sh_addr, /* virtual address */
Elf32_Off sh_offset, /* file offset */
Elf32_Word sh_size, /* section size */
Elf32_Word sh_link, /* misc info */
Elf32_Word sh_info, /* misc info */
Elf32_Word sh_addralign, /* memory alignment */
Elf32_Word sh_entsize /* entry size if table */
) ;
static void SetDATA (Elf_Data *, Elf_Type, size_t, off_t, size_t);
static void SetSYMBOL (Elf32_Sym *, int, Elf32_Word,
Elf32_Addr, unsigned char, Elf32_Half) ;
/* ---------------------------------------------------------------
* SetDATA
* - Installation d'un bloc de donnees du format ELF
* ---------------------------------------------------------------
*/
static void SetDATA (Elf_Data *data,
Elf_Type d_type,
size_t d_size,
off_t d_off,
size_t d_align)
{
data->d_type = d_type ;
data->d_size = d_size ;
data->d_off = d_off ;
data->d_align = d_align ;
data->d_version = EV_CURRENT ;
if (d_size)
data->d_buf = malloc ( d_size);
else
data->d_buf = NULL ;
}
/* ---------------------------------------------------------------
* SetSYMBOL
* ---------------------------------------------------------------
*/
static void SetSYMBOL (Elf32_Sym *psymb, int index, Elf32_Word nameindex,
Elf32_Addr value, unsigned char info, Elf32_Half sectionindex)
{
(psymb+index)->st_name = nameindex ;
(psymb+index)->st_value = value ;
(psymb+index)->st_size = 0 ;
(psymb+index)->st_info = info ;
(psymb+index)->st_other = 0 ;
(psymb+index)->st_shndx = sectionindex;
}
/* ---------------------------------------------------------------
* SetSHDR
* ---------------------------------------------------------------
*/
static void SetSHDR (
Elf32_Shdr *shdr,
Elf32_Word sh_name, /* section name */
Elf32_Word sh_type, /* SHT_... */
Elf32_Word sh_flags, /* SHF_... */
Elf32_Addr sh_addr, /* virtual address */
Elf32_Off sh_offset, /* file offset */
Elf32_Word sh_size, /* section size */
Elf32_Word sh_link, /* misc info */
Elf32_Word sh_info, /* misc info */
Elf32_Word sh_addralign, /* memory alignment */
Elf32_Word sh_entsize /* entry size if table */
)
{
shdr->sh_name = sh_name ;
shdr->sh_type = sh_type ;
shdr->sh_flags = sh_flags;
shdr->sh_addr = sh_addr ;
shdr->sh_offset =sh_offset ;
shdr->sh_size = sh_size;
shdr->sh_link = sh_link ;
shdr->sh_info = sh_info ;
shdr->sh_addralign = sh_addralign;
shdr->sh_entsize = sh_entsize ;
}
/* ---------------------------------------------------------------
* main - assembleur
* ---------------------------------------------------------------
*/
int main (int argc, char *argv[]) {
FILE *inputf ; /* descripteur de fichier d'entree */
int result_analyse ; /* resultat de la premiere phase d'analyse. 0 si ok */
int result_verif ; /* resultat de la phase d'analyse contextuelle.
0 si ok. */
FILE *p_fd_listing ; /* descripteur du listing de sortie */
int fd_object ; /* descripteur de fichier de sortie */
int fd_listing ; /* descripteur du fichier de listing */
char nom_listing [100] ; /* nom du fichier contenant le listing d assemblage */
char nom_out [100] ; /* nom du fichier de sortie */
Elf *elf ; /* descripteur du fichier ELF de sortie */
int modif_fich_sortie ; /* booleen modifie par la presence de l option -o */
int trace ; /* booleen modifie par la presence de l option -v */
/* sdd interne a remplir par analyse et a retravailler ensuite */
static Elem LeProg [MAX_LIGNES_LOG] ;
int nbLigneLog ;
/* -----------------------------------------------------------------------------------
* Analyse des arguments de la ligne de commande
* Possibilite d option
* -v : pour des informations sur le deroulement du programme
* -o <nom> : pour choisir le nom du fichier de sortie
* -----------------------------------------------------------------------------------
*/
modif_fich_sortie = 0 ;
trace = 0 ;
switch (argc) {
case 2 : break ;
sprintf(nom_out, "%s.o", argv[1]) ;
case 3 : if (!strcmp (argv[2], "-v" )) {
trace = 1 ;
sprintf(nom_out, "%s.o", argv[1]) ;
break ;
}
else {
printf ("\n%s : option invalide : %s\n\n",
argv[0], argv [2]);
exit (1) ;
}
case 4 : if (!strcmp (argv[2], "-o" )) {
sprintf(nom_out, "%s.o", argv[3]) ;
break ;
}
else {
printf ("\n%s : option invalide : %s\n\n",
argv[0], argv [2]);
exit (1) ;
}
default : printf ("\n%s : nombre de parametres de commande incorrect \n\n",
argv[0]) ;
exit (1) ;
}
if ((inputf = fopen(argv[1], "r" )) == NULL) {
printf("%s : impossible d'ouvrir : %s\n", argv[0], argv[1]);
exit(1);
}
if (trace)
printf
("\n************************************************************
* Verification de la ligne de commande achevee avec succes *
************************************************************ \n\n" ) ;
/* -----------------------------------------------------------------------------------
* Analyse - phase 1 : remplit les structures de donnees de AA.h
* Arret a la premiere erreur detectee
* On produira tout de meme un listing avec le fichier incomplet
* par contre pas de fichier binaire relogeable
* -----------------------------------------------------------------------------------
*/
result_analyse = Analyse (inputf, LeProg, &nbLigneLog) ;
if (result_analyse != 0)
printf ("\n%s : erreur de syntaxe - poursuite \n\n",
argv[0]) ;
close (inputf) ;
if (trace)
printf
("\n****************************
* Analyse lexicale achevee *
**************************** \n\n" ) ;
/* -----------------------------------------------------------------------------------
* Analyse - phase 2 : verifications contextuelles
* pas de double definition d etiquette, modes d adressage autorises
* taille demandee positive pour reservations non initialisees
* taille de zone reservee suffisante pour stocker une donnee initialisante
* borne d alignement positive
* -----------------------------------------------------------------------------------
*/
result_verif = Verif (LeProg, nbLigneLog) ;
if (result_verif != 0)
printf ("\n%s : erreur de syntaxe contextuelle - poursuite \n\n",
argv[0]) ;
if (trace)
printf
("\n****************************************
* Verifications contextuelles achevees *
**************************************** \n\n" ) ;
/* Enrichissement de la structure de donnees
* calcul des valeurs et des zones de def des symboles,...
* ----------------------------------------------------
*/
Decoration (LeProg, nbLigneLog) ;
/* -----------------------------------------------------------------------------------
* Production du listing d assemblage
* -----------------------------------------------------------------------------------
*/
sprintf (nom_listing, "%s.l", inputf) ;
/* ouverture d un fichier de listing en ecriture */
unlink (nom_listing) ;
p_fd_listing = fopen (nom_listing, "w" ) ;
if (fd_listing == -1) {
perror ("Kerala(linux-pentium)" ) ;
exit (1) ;
}
fchmod (fd_listing, S_IRUSR|S_IWUSR) ;
Remplir_Listing (LeProg, nbLigneLog, p_fd_listing) ;
/* Generation de code =
* production du fichier ELF
* -------------------------
*/
sprintf (nom_out, "out.o" ) ;
/* ouverture d'un fichier ELF en ecriture */
unlink (nom_out);
fd_object = open(nom_out, O_WRONLY|O_CREAT|O_TRUNC) ;
if (fd_object == -1) {
perror ("Kerala(linux-pentium)" ) ;
exit(1);
}
fchmod (fd_object, S_IRUSR|S_IWUSR);
/* coordinate versions of the ELF library */
(void) elf_version(EV_CURRENT);
/* Obtain the ELF descriptor */
if ((elf = elf_begin(fd_object, ELF_C_WRITE, NULL)) == NULL)
exit(1);
GenererObjet (elf) ;
elf_update (elf,ELF_C_WRITE) ;
elf_end (elf);
close (fd_object) ;
}
/* pre-declarations - voir ci-dessous */
static int VerifInst (Elem) ;
static int VerifReservInit(Elem) ;
/* Fonctions tests */
int EstReg32 (char *nom) {
int i ;
for (i = 0; ; i++) {
if (!strcmp (" ", tableNomsRegs32 [i]))
break ;
if (!strcmp (nom, tableNomsRegs32 [i]))
return 1 ;
}
return 0 ;
}
int EstReg16 (char *nom) {
int i ;
for (i = 0; ; i++) {
if (!strcmp (" ", tableNomsRegs16 [i]))
break ;
if (!strcmp (nom, tableNomsRegs16 [i]))
return 1 ;
}
return 0 ;
}
int EstReg8 (char *nom) {
int i ;
for (i = 0; ; i++) {
if (!strcmp (" ", tableNomsRegs8 [i]))
break ;
if (!strcmp (nom, tableNomsRegs8 [i]))
return 1 ;
}
return 0 ;
}
int EstValImm8 (long val) {
if ((val < SHRT_MIN ) || (val > USHRT_MAX ))
return 0;
else return 1;
}
int EstValImm16 (long val) {
if ((val < INT_MIN) || (val > UINT_MAX))
return 0;
else return 1;
}
int EstValSigne8 (long val){
if ((val < SHRT_MIN ) || (val > SHRT_MAX ))
return 0;
else return 1;
}
/* ------------------------------------------------------------------------
*/
int EstInst2ParB (char *nom) {
int i ;
for (i = 0; ; i++) {
if (!strcmp (" ", tableInstructions2ParB [i]))
break ;
if (!strcmp (nom, tableInstructions2ParB [i]))
return 1 ;
}
return 0 ;
}
int EstInst2ParW (char *nom) {
int i ;
for (i = 0; ; i++) {
if (!strcmp (" ", tableInstructions2ParW [i]))
break ;
if (!strcmp (nom, tableInstructions2ParW [i]))
return 1 ;
}
return 0 ;
}
int EstInst2ParL (char *nom) {
int i ;
for (i = 0; ; i++) {
if (!strcmp (" ", tableInstructions2ParL [i]))
break ;
if (!strcmp (nom, tableInstructions2ParL [i]))
return 1 ;
}
return 0 ;
}
int EstSautCond (char *nom) {
int i ;
for (i = 0; ; i++) {
if (!strcmp (" ", tableSautCond [i]))
break ;
if (!strcmp (nom, tableSautCond [i]))
return 1 ;
}
return 0 ;
}
/* --------------------------------------------------------------------------------------------------
*/
/* predeclarations */
int EstModeAdInst2ParB (NatParam, Param, NatParam, Param) ;
int EstModeAdInst2parW (NatParam, Param, NatParam, Param) ;
int EstModeAdInst2parL (NatParam, Param, NatParam, Param) ;
int EstModeAdInst2ParB (NatParam natp0, Param p0, NatParam natp1, Param p1) {
switch (natp0) {
case P_NOMREG :
if (EstReg8(p0.u.nomreg)&&(((natp1 == P_NOMREG)&&EstReg8(p1.u.nomreg)) || ((natp1==P_INDIR)&&(p1.u.indir.nbreg == 1)) ||
((natp1==P_INDEX_INDIR)&&(p1.u.index_indir.nbreg == 1)) || (natp1==P_NOMBRE) || (natp1==P_ETIQUETTE)))
return 1;
case P_DOLLAR_NB :
if (EstValImm8(p0.u.dollar_nb)&&(((natp1 == P_NOMREG)&&EstReg8(p1.u.nomreg)) || ((natp1==P_INDIR)&&(p1.u.indir.nbreg == 1)) ||
((natp1==P_INDEX_INDIR)&&(p1.u.index_indir.nbreg == 1)) || (natp1==P_NOMBRE) || (natp1==P_ETIQUETTE)))
return 1;
case P_DOLLAR_ETIQ :
if (((natp1 == P_NOMREG)&&EstReg8(p1.u.nomreg)) || ((natp1==P_INDIR)&&(p1.u.indir.nbreg == 1)) ||
((natp1==P_INDEX_INDIR)&&(p1.u.index_indir.nbreg == 1)) || (natp1==P_NOMBRE) || (natp1==P_ETIQUETTE))
return 1;
case P_INDIR :
if ((p0.u.indir.nbreg == 1)&&((natp1==P_NOMREG) && (EstReg8(p1.u.nomreg))))
return 1;
case P_INDEX_INDIR :
if ((p0.u.index_indir.nbreg == 1)&&((natp1==P_NOMREG) && (EstReg8(p1.u.nomreg))))
return 1;
case P_NOMBRE :
case P_ETIQUETTE :
if ((natp1==P_NOMREG) && (EstReg8(p1.u.nomreg)))
return 1;
default:
return 0 ;
}
}
int EstModeAdInst2parW (NatParam natp0, Param p0, NatParam natp1, Param p1) {
switch (natp0) {
case P_NOMREG :
if (EstReg16(p0.u.nomreg)&&(((natp1 == P_NOMREG)&&EstReg16(p1.u.nomreg)) || ((natp1==P_INDIR)&&(p1.u.indir.nbreg == 1)) ||
((natp1==P_INDEX_INDIR)&&(p1.u.index_indir.nbreg == 1)) || (natp1==P_NOMBRE) || (natp1==P_ETIQUETTE)))
return 1;
case P_DOLLAR_NB :
if (EstValImm16(p0.u.dollar_nb)&&(((natp1 == P_NOMREG)&&EstReg16(p1.u.nomreg)) || ((natp1==P_INDIR)&&(p1.u.indir.nbreg == 1)) ||
((natp1==P_INDEX_INDIR)&&(p1.u.index_indir.nbreg == 1)) || (natp1==P_NOMBRE) || (natp1==P_ETIQUETTE)))
return 1;
case P_DOLLAR_ETIQ :
if (((natp1 == P_NOMREG)&&EstReg16(p1.u.nomreg)) || ((natp1==P_INDIR)&&(p1.u.indir.nbreg == 1)) ||
((natp1==P_INDEX_INDIR)&&(p1.u.index_indir.nbreg == 1)) || (natp1==P_NOMBRE) || (natp1==P_ETIQUETTE))
return 1;
case P_INDIR :
if ((p0.u.indir.nbreg == 1)&&((natp1==P_NOMREG) && (EstReg16(p1.u.nomreg))))
return 1;
case P_INDEX_INDIR :
if ((p0.u.index_indir.nbreg == 1)&&((natp1==P_NOMREG) && (EstReg16(p1.u.nomreg))))
return 1;
case P_NOMBRE :
case P_ETIQUETTE :
if ((natp1==P_NOMREG) && (EstReg16(p1.u.nomreg)))
return 1;
default:
return 0 ;
}
}
int EstModeAdInst2parL (NatParam natp0, Param p0, NatParam natp1, Param p1) {
switch (natp0) {
case P_NOMREG :
if (EstReg32(p0.u.nomreg)&&(((natp1 == P_NOMREG)&&EstReg32(p1.u.nomreg)) || ((natp1==P_INDIR)&&(p1.u.indir.nbreg == 1)) ||
((natp1==P_INDEX_INDIR)&&(p1.u.index_indir.nbreg == 1)) || (natp1==P_NOMBRE) || (natp1==P_ETIQUETTE)))
return 1;
case P_DOLLAR_NB :
if (((natp1 == P_NOMREG)&&EstReg32(p1.u.nomreg)) || ((natp1==P_INDIR)&&(p1.u.indir.nbreg == 1)) ||
((natp1==P_INDEX_INDIR)&&(p1.u.index_indir.nbreg == 1)) || (natp1==P_NOMBRE) || (natp1==P_ETIQUETTE))
return 1;
case P_DOLLAR_ETIQ :
if (((natp1 == P_NOMREG)&&EstReg32(p1.u.nomreg)) || ((natp1==P_INDIR)&&(p1.u.indir.nbreg == 1)) ||
((natp1==P_INDEX_INDIR)&&(p1.u.index_indir.nbreg == 1)) || (natp1==P_NOMBRE) || (natp1==P_ETIQUETTE))
return 1;
case P_INDIR :
if ((p0.u.indir.nbreg == 1)&&((natp1==P_NOMREG) && (EstReg32(p1.u.nomreg))))
return 1;
case P_INDEX_INDIR :
if ((p0.u.index_indir.nbreg == 1)&&((natp1==P_NOMREG) && (EstReg32(p1.u.nomreg))))
return 1;
case P_NOMBRE :
case P_ETIQUETTE :
if ((natp1==P_NOMREG) && (EstReg32(p1.u.nomreg)))
return 1;
default:
return 0 ;
}
}
int EstModeAdLea (NatParam natp0, Param p0, NatParam natp1, Param p1){
if (natp1==P_NOMREG){
switch(natp0) {
case P_INDIR :
if (((p0.u.indir.nbreg == 1)&&(EstReg32(p0.u.indir.nomreg1)))&&
((natp1 == P_NOMREG)&&EstReg32(p1.u.indir.nomreg1)))
return 1;
case P_INDEX_INDIR :
if (((p0.u.index_indir.nbreg == 1)&&EstReg32(p0.u.index_indir.nomreg1))&&
((natp1 == P_NOMREG)&&EstReg32(p1.u.indir.nomreg1)))
return 1;
case P_NOMBRE :
case P_ETIQUETTE :
if ((natp1==P_NOMREG) && (EstReg32(p1.u.nomreg)))
return 1;
default :
return 0;
}
}
}
int EstModeAdPopw (NatParam natp0, Param p0){
switch(natp0) {
case P_INDIR :
if ((p0.u.indir.nbreg == 1)&&(EstReg32(p0.u.indir.nomreg1)))
return 1;
case P_INDEX_INDIR :
if ((p0.u.index_indir.nbreg == 1)&&EstReg32(p0.u.index_indir.nomreg1))
return 1;
case P_NOMBRE :
case P_ETIQUETTE :
return 1;
case P_NOMREG :
if (EstReg16(p0.u.nomreg))
return 1;
default :
return 0;
}
}
on va arreter la 
---------------
Les accents sont en option... j'ai un clavier qwertz.