simple linker.ld file broke the executable MinGW - c

I have tried a simple linker script in MinGW using the following commands
gcc -Wall -c boot.c
ld boot.o -o boot.exe -T linker.ld
boot.c contains
int my_main(void){
return 0x1000;
}
linker.ld contains
ENTRY(my_main)
SECTIONS
{
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
the linker output is warning warning: cannot find entry symbol my_main; defaulting to 00000000
and the virtual addresses of the sections are weird values:
C:\src>objdump -h boot.exe
boot.exe: file format pei-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000000c 00000000 00000000 00000200 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .rdata 00000024 00001000 00001000 00000400 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .eh_fram 00000038 00002000 00002000 00000600 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
and when i try to execute it, windows says "This app can't run in your PC"

Related

String literal not working if passed as argument

I'm trying to write a bootloader in c and I noticed that string literals only worked if I passed them as a char *.
If it Could help:
when I converted both versions to assembly I found one difference that was only in the working version which is
mov DWORD PTR -8[ebp], eax
push DWORD PTR -8[ebp]
just before calling puts
Here's my code :
asm("jmp main");
void putc(char c) {
asm volatile("mov %%al, %0" :: "a"(c));
asm volatile("mov %ah, 0x0e");
asm volatile("int 0x10");
}
void puts(const char *s) {
while(*s) putc(*s++);
}
void newl() {
char s[] = { 0x0D, 0x0A, 0 };
puts(s);
}
void clear() {
asm volatile("mov ah, 0");
asm volatile("mov al, 0x3");
asm volatile("int 0x10");
}
void __attribute__((optimize("-O0"))) main() {
clear();
char * a = "Hello World";
puts(a); // WORKS
puts("Hello World"); // DOESN'T WORK (DOES NOT WRITE ANYTHING)
newl();
}
LD.LD :
ENTRY(main)
SECTIONS
{
. = 0x7C00;
.text : AT(0x7C00)
{
*(.text);
}
.sig : AT(0x7C00 + 510)
{
SHORT(0xaa55);
}
/DISCARD/ : {
*(.comment)
*(.eh_frame)
}
}
How I compiled:
gcc -m16 -c -ffreestanding -fno-pie -fno-exceptions -masm=intel -s -Os -static -Wall -ffunction-sections -fdata-sections main.cpp -o main.o
ld -m elf_i386 -o main.elf -T ld.ld main.o
objcopy -O binary main.elf main.bin
and I ran it with : qemu-system-x86_64 -fda main.bin
with char * a = "Hello World"; puts(a); :
objdump -h:
Idx Name Size VMA LMA File off Algn
0 .text 00000003 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000037 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000037 2**0
ALLOC
3 .rodata 0000000c 00000000 00000000 00000037 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .text.main 00000051 00000000 00000000 00000043 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
5 .text.putc 00000014 00000000 00000000 00000094 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
6 .text.puts 0000002f 00000000 00000000 000000a8 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
7 .text.newl 00000029 00000000 00000000 000000d7 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
8 .text.clear 00000008 00000000 00000000 00000100 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
9 .comment 0000001f 00000000 00000000 00000108 2**0
CONTENTS, READONLY
10 .note.GNU-stack 00000000 00000000 00000000 00000127 2**0
CONTENTS, READONLY
11 .eh_frame 000000b8 00000000 00000000 00000128 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
with puts("Hello World");:
objdump -h:
Idx Name Size VMA LMA File off Algn
0 .text 00000003 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000037 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000037 2**0
ALLOC
3 .rodata 0000000c 00000000 00000000 00000037 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .text.main 00000047 00000000 00000000 00000043 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
5 .text.putc 00000014 00000000 00000000 0000008a 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
6 .text.puts 0000002f 00000000 00000000 0000009e 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
7 .text.newl 00000029 00000000 00000000 000000cd 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
8 .text.clear 00000008 00000000 00000000 000000f6 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
9 .comment 0000001f 00000000 00000000 000000fe 2**0
CONTENTS, READONLY
10 .note.GNU-stack 00000000 00000000 00000000 0000011d 2**0
CONTENTS, READONLY
11 .eh_frame 000000b8 00000000 00000000 00000120 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

"kernel must be loaded first"

I wrote a mini-boot loader and a simple kernel that print a string. I followed step-by-step this playlist(First 3 videos to be precise!). Anyway, when I boot my virtual machine(with my ISO) I get those messages:
"error: no multiboot header found."
"error: you need to load the kernel first."
I tried to modify some section of the assembly code in the boot file but without success.
Here is the code:
boot.s
.set MAGIC, 0x1badb002
.set FLAGS, (1<<0 | 1<<1)
.set CHECKSUM, -(MAGIC + FLAGS)
.section .multiboot
.long MAGIC
.long FLAGS
.long CHECKSUM
.section .text
.extern kernel_main
.extern call_constructors
.global loader
loader:
mov $kernel_stack, %esp
call call_constructors
push %eax
push %ebx
call kernel_main
_stop:
cli
hlt
jmp _stop
.section .bss
.space 2*1024*1024 ;#2 MiB
kernel_stack:
kernel.c
#include <sys/types.h>
void printf(char * str)
{
uint16_t * VideoMemory = (uint16_t *)0xb8000;
for(int32_t i = 0; str[i] != '\0'; i++)
VideoMemory[i] = (VideoMemory[i] & 0xFF00) | str[i];
}
typedef void (*constructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void call_constructors()
{
for(constructor* i = &start_ctors; i != &end_ctors; i++)
(*i)();
}
extern "C" void kernel_main(const void * multiboot_structure, uint32_t magic_number)
{
printf("Denos - Version: 0.0.1a");
for(;;);
}
NOTE: sys/types.h comes from my lib. which is included as argument in gcc.
linker.ld
ENTRY(loader)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)
SECTIONS
{
. = 0x0100000;
.text :
{
*(.multiboot)
*(.text*)
*(.rodata)
}
.data :
{
start_ctors = .;
KEEP(*( .init_array ));
KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
end_ctors = .;
*(.data)
}
.bss :
{
*(.bss)
}
/DISCARD/ :
{
*(.fini_array*)
*(.comment)
}
}
Makefile
GPPPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -I ../include/
ASPARAMS = --32
objects = boot.o kernel.o
run: denos.iso
(killall VirtualBox && sleep 1) || true
VirtualBox --startvm 'denos' &
%.o: %.c
gcc $(GPPPARAMS) -o $# -c $<
%.o: %.s
as $(ASPARAMS) -o $# $<
kernel.bin : linker.ld $(objects)
ld $(LDPARAMS) -T $< -o $# $(objects)
install: kernel.bin
sudo cp $< ./boot/kernel.bin
denos.iso: kernel.bin
mkdir iso
mkdir iso/boot
mkdir iso/boot/grub
cp kernel.bin iso/boot/kernel.bin
echo 'set timeout=0' > iso/boot/grub/grub.cfg
echo 'set default=0' >> iso/boot/grub/grub.cfg
echo '' >> iso/boot/grub/grub.cfg
echo 'menuentry "Denos" {' >> iso/boot/grub/grub.cfg
echo ' multiboot /boot/kernel.bin' >> iso/boot/grub/grub.cfg
echo ' boot' >> iso/boot/grub/grub.cfg
echo '}' >> iso/boot/grub/grub.cfg
grub-mkrescue --output=denos.iso iso
rm -rf iso
mv -f denos.iso /home/data/libvirt_iso/
objdump -x kernel.bin(Requested)
kernel.bin: file format elf32-i386
kernel.bin
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0010000c
Program Header:
LOAD off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**21
filesz 0x001001ac memsz 0x003001ac flags rwx
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**4
filesz 0x00000000 memsz 0x00000000 flags rwx
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000100 00100000 00100000 00100000 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .eh_frame 000000a0 00100100 00100100 00100100 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .got.plt 0000000c 001001a0 001001a0 001001a0 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .bss 00200000 001001ac 001001ac 001001ac 2**0
ALLOC
SYMBOL TABLE:
00100000 l d .text 00000000 .text
00100100 l d .eh_frame 00000000 .eh_frame
001001a0 l d .got.plt 00000000 .got.plt
001001ac l d .bss 00000000 .bss
00000000 l df *ABS* 00000000 boot.o
1badb002 l *ABS* 00000000 MAGIC
00000003 l *ABS* 00000000 FLAGS
e4524ffb l *ABS* 00000000 CHECKSUM
003001ac l .bss 00000000 kernel_stack
0010001d l .text 00000000 _stop
00000000 l df *ABS* 00000000 kernel.c
00000000 l df *ABS* 00000000
001001a0 l O .got.plt 00000000 _GLOBAL_OFFSET_TABLE_
001001a0 g .got.plt 00000000 start_ctors
001000e0 g F .text 00000000 .hidden __x86.get_pc_thunk.ax
001000c2 g F .text 0000001e kernel_main
001000e4 g F .text 00000000 .hidden __x86.get_pc_thunk.bx
001001a0 g .got.plt 00000000 end_ctors
00100088 g F .text 0000003a call_constructors
00100021 g F .text 00000067 _Z6printfPc
0010000c g .text 00000000 loader
I'm so sorry I wasted someone times. I checked 'Makefile' file and I figured out that I was missing 'LDPARAMS = -melf_i386'. Now it boot and print
Thanks anyway.

Object file created by objcopy is not compatible

I have created an object file from a binary file using objcopy as below:
objcopy -I binary -O elf32-little --rename-section .data=.text file.bin file.o
In one of the linker script sections I have included the following to place that file into that section:
file.o (.text)
But I get the following error:
skipping incompatible file.o when searching for file.o
error: ld returned 1 exit status
I am developing for a arm microcontroller so I believe the file format "elf32-little" is correct.
Any help is much appreciated.
#####################################################################
UPDATE FOLLOWING THE INCBIN path:
I have tried a new approach and although I have made some progress still not quite yet there.
This is my assembly file:
.section .text.audio_binary
.global audio_start
audio_start:
.incbin "AudioData.bin"
.global audio_start
audio_end:
.byte 0
.global audio_size
audio_size:
.int audio_start - audio_start
This is the object file I get:
raw_audio_binary.o: file format elf32-little
SYMBOL TABLE:
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .text.audio_binary 00000000 .text.audio_binary
00069a78 l .text.audio_binary 00000000 audio_end
00000000 l .text.audio_binary 00000000 $d
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g .text.audio_binary 00000000 audio_start
00069a79 g .text.audio_binary 00000000 audio_size
And this is the section I have in my linker script:
.text_Flash3 : ALIGN(4)
{
FILL(0xff)
*(.text.$Flash3*)
*(.text.$AUDIO*) *(.rodata.$Flash3*)
*(.text.audio_binary*) /* audio binary */
*(.rodata.$AUDIO*) } > AUDIO
For some reason the linker does NOT place the data in this section (or in any).
Any ideas what is wrong?
I apologise in advance if something is very wrong here, I am new to linker scripts so still understanding them...
If you have a sufficiently recent version of GAS, you can use this to create an object file from a binary input file using the .incbin directive:
.section .rodata
.globl input_wav
input_wav:
.incbin "input.wav"
.globl input_wav_size
input_wav_size:
.long . - input_wav

Difference between OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4) in linker script

Among other things I am trying to understand the difference between OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4).
Assume we have next files (I have used linker script example from here as a basis):
main.c:
int main(void)
{
test_1();
test_2();
return 0;
}
main.lds:
OUTPUT_ARCH(arm)
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
test_1.c:
void test_1(void)
{
return;
}
test_2.c:
void test_2(void)
{
return;
}
If we compile it and dump its content we have next:
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe test_1.c -c
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe test_2.c -c
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x test_1.o
test_1.o: file format elf32-littlearm
test_1.o
architecture: arm, flags 0x00000010:
HAS_SYMS
start address 0x00000000
private flags = 200: [APCS-32] [FPA float format] [software FP]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000014 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000048 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000048 2**0
ALLOC
3 .comment 00000012 00000000 00000000 00000048 2**0
CONTENTS, READONLY
4 .ARM.attributes 00000010 00000000 00000000 0000005a 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 test_1.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g F .text 00000014 test_1
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -static -nostartfiles -T main.lds -o main.elf test_1.o test_2.o
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x main.elf
main.elf: file format elf32-littlearm
main.elf
architecture: arm, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00010000
Program Header:
LOAD off 0x00008000 vaddr 0x00010000 paddr 0x00010000 align 2**15
filesz 0x00000028 memsz 0x00000028 flags r-x
private flags = 200: [APCS-32] [FPA float format] [software FP]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000028 00010000 00010000 00008000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .comment 00000011 00000000 00000000 00008028 2**0
CONTENTS, READONLY
2 .ARM.attributes 00000010 00000000 00000000 00008039 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00010000 l d .text 00000000 .text
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 l df *ABS* 00000000 test_1.c
00000000 l df *ABS* 00000000 test_2.c
00010014 g F .text 00000014 test_2
00010000 g F .text 00000014 test_1
But if I change OUTPUT_ARCH(arm) to OUTPUT_ARCH(armv4), I get an error from linker:
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -static -nostartfiles -T main.lds -o main.elf test_1.o test_2.o
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: error: test_1.o uses software FP, whereas main.elf uses hardware FP
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: failed to merge target specific data of file test_1.o
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: error: test_2.o uses software FP, whereas main.elf uses hardware FP
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: failed to merge target specific data of file test_2.o
collect2: ld returned 1 exit status
It can be fixed by specifying -mfloat-abi=hard option. In this case there is a difference in private flags comparing with previous output:
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -mfloat-abi=hard test_1.c -c
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -mfloat-abi=hard test_2.c -c
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x test_1.o
test_1.o: file format elf32-littlearm
test_1.o
architecture: arm, flags 0x00000010:
HAS_SYMS
start address 0x00000000
private flags = 0: [APCS-32] [FPA float format]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000014 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000048 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000048 2**0
ALLOC
3 .comment 00000012 00000000 00000000 00000048 2**0
CONTENTS, READONLY
4 .ARM.attributes 00000010 00000000 00000000 0000005a 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 test_1.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g F .text 00000014 test_1
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -static -nostartfiles -T main.lds -o main.elf test_1.o test_2.o
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x main.elf
main.elf: file format elf32-littlearm
main.elf
architecture: arm, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00010000
Program Header:
LOAD off 0x00008000 vaddr 0x00010000 paddr 0x00010000 align 2**15
filesz 0x00000028 memsz 0x00000028 flags r-x
private flags = 0: [APCS-32] [FPA float format]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000028 00010000 00010000 00008000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .comment 00000011 00000000 00000000 00008028 2**0
CONTENTS, READONLY
2 .ARM.attributes 00000010 00000000 00000000 00008039 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00010000 l d .text 00000000 .text
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 l df *ABS* 00000000 test_1.c
00000000 l df *ABS* 00000000 test_2.c
00010014 g F .text 00000014 test_2
00010000 g F .text 00000014 test_1
Does it mean that OUTPUT_ARCH(armv4) causes linker to generate output solely for hard float?
In general, what is the difference between OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4)?
According to ld manual OUTPUT_ARCH() specifies a particular output machine architecture.
The argument is one of the names used by the BFD library.
But I have found no clear information about BFD library except general information.
I use arm-elf toolchain from here (Binutils 2.22, GCC 4.6.3, Newlib 1.2.0, GDB 7.4).
Thank you in advance for help.
UPDATE 1:
This update is a reply for the comment below.
Compiler -v output from old toolchain we use now:
Using built-in specs.
Target: arm-elf
Configured with: ../gcc-4.4.1/configure --target=arm-elf --host=i686-pc-mingw32 --with-cpu=xscale --without-stabs -nfp --prefix=/c/cross-gcc/4.4.1 --disable-nls --disable-shared --disable-__cxa_atexit
--enable-threads --with-gnu-gcc --with-gnu-ld --with-gnu-as --with-dwarf2 --enable-languages=c,c++ --enable-interwork --disable-multilib --with-gmp=/c/cross-gcc/4.4.1 --with-mpfr=/c/cross-gcc/4.4.1 -
-with-newlib --with-headers=../../newlib-1.17.0/newlib-1.17.0/newlib/libc/include --disable-libssp --disable-libstdcxx-pch --disable-libmudflap --disable-libgomp -v
Thread model: single
gcc version 4.4.1 (GCC)
Compiler -v output from newer toolchain I used in the examples (SysGCC arm-elf):
Using built-in specs.
COLLECT_GCC=arm-elf-gcc.exe
COLLECT_LTO_WRAPPER=c:/sysgcc/arm-elf/bin/../libexec/gcc/arm-elf/4.6.3/lto-wrapper.exe
Target: arm-elf
Configured with: ../gcc-4.6.3/configure --target arm-elf --enable-win32-registry=SysGCC-arm-elf-4.6.3 --prefix /c/gnu/auto/bu-2.22+gcc-4.6.3+gmp-4.2.4+mpfr-2.4.1+mpc-0.8+newlib-1.20.0-arm-elf/ --enabl
e-languages=c,c++ --disable-nls --with-newlib --with-headers=../newlib-1.20.0/newlib/libc/include --enable-interwork --enable-multilib --with-float=soft
Thread model: single
gcc version 4.6.3 (GCC)
There is no difference between linker output for OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4) for old compiler. I think I should have checked it before.
Seems that it is an answer to this question.
My goal is to use the combination -mfpu=vfpv3 -mfloat-abi=hard, but according to Debian documentation and GCC 4.4.7 manual this combination is not supported by GCC 4.4.
In fact if I try to compile with -mfpu=vfpv3 -mfloat-abi=hard by old compiler, it returns error:
sorry, unimplemented: -mfloat-abi=hard and VFP
Still and all it is possible to use -mfpu=vfpv3 -mfloat-abi=softfp with old compiler, but according to this comparison it gives big overhead for small routines.

What does an "Algn" of 2**2 and 2**0 mean in the output of objdump?

What does this mean in below file? 2**2 and 2**0
$ objdump -h main.o
main.o: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000000b 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000040 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000040 2**2
ALLOC
3 .note.GNU-stack 00000000 00000000 00000000 00000040 2**0
CONTENTS, READONLY, CODE
I would assume that 2**2 means 22, or 4 byte alignment, while 2**0 means no (one byte) alignment.
This value comes from the sh_addralign field of the ELF section header. The ELF specification states (emphasis mine):
sh_addralign Some sections have address alignment constraints. For example, if a section holds a
doubleword, the system must ensure doubleword alignment for the entire section.
That is, the value of sh_addr must be congruent to 0, modulo the value of
sh_addralign. Currently, only 0 and positive integral powers of two are allowed.
Values 0 and 1 mean the section has no alignment constraints.
As Ray Toal mentioned, since the alignment must be a power of two, it only makes sense that objdump would express this value as a power of two with the 2**x notation.
Note that in some languages, like Python and FORTRAN, ** is a power or exponentiation operator.
Looking at objdump.c, we see:
static void
dump_section_header (bfd *abfd, asection *section,
void *ignored ATTRIBUTE_UNUSED)
{
// ...
printf (" %08lx 2**%u", (unsigned long) section->filepos,
bfd_get_section_alignment (abfd, section));
And in objdump.h:
#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
where the alignment_power member of bfd is:
/* The alignment requirement of the section, as an exponent of 2 -
e.g., 3 aligns to 2^3 (or 8). */
unsigned int alignment_power;

Resources