SF.net SVN: geany-plugins:[368] trunk/geanygdb/src/gdb-ui-main.c

eht16 at users.sourceforge.net eht16 at xxxxx
Mon Jan 5 16:31:21 UTC 2009


Revision: 368
          http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=368&view=rev
Author:   eht16
Date:     2009-01-05 16:31:21 +0000 (Mon, 05 Jan 2009)

Log Message:
-----------
Support opening big endian elf files (patch by Cameron Hart, thanks).

Modified Paths:
--------------
    trunk/geanygdb/src/gdb-ui-main.c

Modified: trunk/geanygdb/src/gdb-ui-main.c
===================================================================
--- trunk/geanygdb/src/gdb-ui-main.c	2009-01-04 23:28:39 UTC (rev 367)
+++ trunk/geanygdb/src/gdb-ui-main.c	2009-01-05 16:31:21 UTC (rev 368)
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <elf.h>
 #include <gtk/gtk.h>
 
 #include "gdb-io.h"
@@ -392,56 +393,84 @@
 
 
 
-// Crude check for "ELF 32-bit LSB [reloc|exec|shared|core] Intel 80386, version 1"
+/* Check for ELF type */
 typedef enum
-{ ELF_RELOC, ELF_EXEC, ELF_SHARED, ELF_CORE, ELF_NOT_ELF } ElfType;
+{ ELF_RELOC, ELF_EXEC, ELF_SHARED, ELF_CORE, ELF_UNKNOWN } ElfType;
 
 static ElfType
-get_elf_type(const char *filename)
+get_elf_type(const char * filename)
 {
-	char buf[32];
-	ElfType rv = ELF_NOT_ELF;
-	int n;
-	FILE *fh = fopen(filename, "r");
-	if (fh)
+	/* There are seperate 32 bit and 64 bit elf headers on linux. The
+	 * bits we are interested in should be in the same location for
+	 * both. */
+	union
 	{
-		memset(buf, 0, sizeof(buf));
-		n = fread(buf, 1, sizeof(buf), fh);
-		fclose(fh);
-		if ((n == sizeof(buf)) &&
-		    (memcmp(buf, "\177ELF", 4) == 0) &&
-		    (memcmp(buf + 5, "\1\1\0\0\0\0\0\0\0\0\0", 11) == 0)
-		    /* && (memcmp(buf+17,"\0\3\0\1",4)==0) *//* <= Intel 80386, version 1 */
-			)
-		{
-			switch (buf[4])
-			{
-				case '\1':
-					break;	/* 32-bit */
-				case '\2':
-					break;	/* 64-bit */
-				default:
-					return ELF_NOT_ELF;
-			}
-			switch (buf[16])
-			{
-				case '\1':
-					return ELF_RELOC;
-				case '\2':
-					return ELF_EXEC;
-				case '\3':
-					return ELF_SHARED;
-				case '\4':
-					return ELF_CORE;
-			}
-		}
+		Elf32_Ehdr ehdr32;
+		Elf64_Ehdr ehdr64;
+	} e_header;
+
+	int read_ehdr;
+	int is_32bit_elf;
+	int is_little_endian;
+	const char* e_type_buf;
+	unsigned int e_type;
+	FILE* file = fopen(filename, "r");
+
+	if (!file)
+		return ELF_UNKNOWN;
+
+	read_ehdr = fread(&e_header, sizeof(e_header), 1, file);
+	fclose(file);
+
+	if (read_ehdr != 1)
+		return ELF_UNKNOWN;
+
+	/* Determine how to read the rest of the header.  */
+	switch (e_header.ehdr32.e_ident[EI_DATA])
+	{
+		default: /* fall through */
+		case ELFDATANONE: /* fall through */
+		case ELFDATA2LSB:
+			is_little_endian = 1;
+			break;
+		case ELFDATA2MSB:
+			is_little_endian = 0;
+		break;
 	}
-	return rv;
+
+	/* For now we only support 32 bit and 64 bit ELF files.  */
+	is_32bit_elf = (e_header.ehdr32.e_ident[EI_CLASS] != ELFCLASS64);
+
+	/* The type field offset and size should be the same between 32 and 64 bit platforms! */
+	if (!is_32bit_elf &&
+		((char*) &e_header.ehdr32.e_type != (char*) &e_header.ehdr64.e_type ||
+		(char*) &e_header.ehdr32.e_machine != (char*) &e_header.ehdr64.e_machine))
+		return ELF_UNKNOWN;
+
+	/* get the type taking endian into account */
+	e_type_buf = (char*) &e_header.ehdr32.e_type;
+	if (is_little_endian)
+		e_type = ((unsigned int) (e_type_buf[0])) | (((unsigned int) (e_type_buf[1])) << 8);
+	else
+		e_type = ((unsigned int) (e_type_buf[1])) | (((unsigned int) (e_type_buf[0])) << 8);
+
+	switch (e_type)
+	{
+		case ET_REL:
+			return ELF_RELOC;
+		case ET_EXEC:
+			return ELF_EXEC;
+		case ET_DYN:
+			return ELF_SHARED;
+		case ET_CORE:
+			return ELF_CORE;
+		default:
+			return ELF_UNKNOWN;
+	}
 }
 
 
 
-
 static void
 load_click(GtkWidget * btn, gpointer user_data)
 {


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Plugins-Commits mailing list